[libcxx-commits] [libcxx] [libc++] Implement a type-safe iterator for optional (PR #154239)

William Tran-Viet via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 7 19:03:46 PST 2026


https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/154239

>From 8cec4dbbede31678f40344b23885156345aebe4e Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 18 Aug 2025 20:09:40 -0400
Subject: [PATCH 01/18] Implement a type-safe iterator for optional

---
 libcxx/include/CMakeLists.txt                 |   1 +
 .../__iterator/upper_bounded_iterator.h       | 174 ++++++++++++++++++
 libcxx/include/module.modulemap.in            |   1 +
 libcxx/include/optional                       |  26 +--
 .../iterator.compile.pass.cpp                 |  55 ++++++
 5 files changed, 246 insertions(+), 11 deletions(-)
 create mode 100644 libcxx/include/__iterator/upper_bounded_iterator.h
 create mode 100644 libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index f9ae22accd687..5d804cca49677 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -516,6 +516,7 @@ set(files
   __iterator/sortable.h
   __iterator/static_bounded_iter.h
   __iterator/unreachable_sentinel.h
+  __iterator/upper_bounded_iterator.h
   __iterator/wrap_iter.h
   __locale
   __locale_dir/check_grouping.h
diff --git a/libcxx/include/__iterator/upper_bounded_iterator.h b/libcxx/include/__iterator/upper_bounded_iterator.h
new file mode 100644
index 0000000000000..1ae0d11ce379f
--- /dev/null
+++ b/libcxx/include/__iterator/upper_bounded_iterator.h
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+/*
+ * __upper_bounded_iterator is an iterator that wraps an underlying iterator.
+ * It stores the underlying container type to prevent mixing iterators, and allow algorithms
+ * to optimize based on the underlying container type.
+ * It also stores the absolute maximum amount of elements the container can have, known at compile-time.
+ * As of writing, the only standard library containers which have this property are inplace_vector and optional.
+ */
+
+#ifndef _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+#define _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+
+#include <__compare/ordering.h>
+#include <__compare/three_way_comparable.h>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/pointer_traits.h>
+#include <__type_traits/is_constructible.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 26
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Iter, class _Container, std::size_t _Max_Elements>
+class __upper_bounded_iterator {
+private:
+  _Iter __iter_;
+
+  friend _Container;
+
+public:
+  using iterator_category = iterator_traits<_Iter>::iterator_category;
+  using iterator_concept  = _Iter::iterator_concept;
+  using value_type        = iter_value_t<_Iter>;
+  using difference_type   = iter_difference_t<_Iter>;
+  using reference         = iter_reference_t<_Iter>;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator()
+    requires is_default_constructible_v<_Iter>
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __upper_bounded_iterator(_Iter __iter) : __iter_(std::move(__iter)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr _Iter __base() const noexcept(noexcept(_Iter(__iter_))) { return __iter_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr auto __max_elements() const noexcept { return _Max_Elements; }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator->() const
+    requires requires { __iter_.operator->(); }
+  {
+    return __iter_.operator->();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator++() {
+    ++__iter_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator operator++(int) {
+    __upper_bounded_iterator __tmp(*this);
+    ++*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator--() {
+    --__iter_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator operator--(int) {
+    __upper_bounded_iterator __tmp(*this);
+    --*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator+=(difference_type __x) {
+    __iter_ += __x;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator-=(difference_type __x) {
+    __iter_ -= __x;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const { return *(*this + __n); }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+  operator==(const __upper_bounded_iterator& __x, const __upper_bounded_iterator& __y) {
+    return __x.__iter_ == __y.__iter_;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
+  operator<=>(const __upper_bounded_iterator& __x, const __upper_bounded_iterator& __y) {
+    if constexpr (three_way_comparable_with<_Iter, _Iter, strong_ordering>) {
+      return __x.__iter_ <=> __y.__iter_;
+    } else {
+      if (__x.__iter_ < __x.__iter_) {
+        return strong_ordering::less;
+      } else if (__x.__iter_ == __y.__iter_) {
+        return strong_ordering::equal;
+      }
+      return strong_ordering::greater;
+    }
+  }
+
+  template <class _Iter2>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
+  operator<=>(const __upper_bounded_iterator& __x,
+              const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements> __y) {
+    if constexpr (three_way_comparable_with<_Iter, _Iter2, strong_ordering>) {
+      return __x.__iter_ <=> __y.__iter_;
+    } else {
+      if (__x.__iter_ < __x.__iter_) {
+        return strong_ordering::less;
+      } else if (__x.__iter_ == __y.__iter_) {
+        return strong_ordering::equal;
+      }
+      return strong_ordering::greater;
+    }
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
+  operator+(const __upper_bounded_iterator& __i, difference_type __n) {
+    auto __tmp = __i;
+    __tmp += __n;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
+  operator+(difference_type __n, const __upper_bounded_iterator& __i) {
+    auto __tmp = __i;
+    __tmp += __n;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
+  operator-(const __upper_bounded_iterator& __i, difference_type __n) {
+    return __i.__iter_ + __n;
+  }
+
+  template <class _Iter2>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+  operator-(const __upper_bounded_iterator& __x,
+            const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements>& __y) {
+    return difference_type(__x.__base() - __y.__base());
+  }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 27178aa1f4378..54d16ea9fef3f 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1544,6 +1544,7 @@ module std [system] {
     module sortable                   { header "__iterator/sortable.h" }
     module static_bounded_iter        { header "__iterator/static_bounded_iter.h" }
     module unreachable_sentinel       { header "__iterator/unreachable_sentinel.h" }
+    module upper_bounded_iterator     { header "__iterator/upper_bounded_iterator.h" }
     module wrap_iter                  { header "__iterator/wrap_iter.h" }
 
     header "iterator"
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 568c86556d156..efd5bbfe517de 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -264,7 +264,6 @@ namespace std {
 #  include <__compare/three_way_comparable.h>
 #  include <__concepts/invocable.h>
 #  include <__config>
-#  include <__cstddef/ptrdiff_t.h>
 #  include <__exception/exception.h>
 #  include <__format/range_format.h>
 #  include <__functional/hash.h>
@@ -272,6 +271,7 @@ namespace std {
 #  include <__functional/unary_function.h>
 #  include <__fwd/functional.h>
 #  include <__iterator/bounded_iter.h>
+#  include <__iterator/upper_bounded_iterator.h>
 #  include <__iterator/wrap_iter.h>
 #  include <__memory/addressof.h>
 #  include <__memory/construct_at.h>
@@ -711,13 +711,17 @@ private:
   using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
 
+#    if _LIBCPP_STD_VER >= 26
+  template <typename _Underlying>
+  using __iter _LIBCPP_NODEBUG = __upper_bounded_iterator<_Underlying, __optional_iterator, 1>;
+
 public:
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-  using iterator       = __bounded_iter<__wrap_iter<__pointer>>;
-  using const_iterator = __bounded_iter<__wrap_iter<__const_pointer>>;
+  using iterator       = __iter<__bounded_iter<__wrap_iter<__pointer>>>;
+  using const_iterator = __iter<__bounded_iter<__wrap_iter<__const_pointer>>>;
 #      else
-  using iterator       = __wrap_iter<__pointer>;
-  using const_iterator = __wrap_iter<__const_pointer>;
+  using iterator       = __iter<__wrap_iter<__pointer>>;
+  using const_iterator = __iter<__wrap_iter<__const_pointer>>;
 #      endif
 
   // [optional.iterators], iterator support
@@ -726,12 +730,12 @@ public:
     auto* __ptr          = std::addressof(__derived_self.__get());
 
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return std::__make_bounded_iter(
+    return iterator(std::__make_bounded_iter(
         __wrap_iter<__pointer>(__ptr),
         __wrap_iter<__pointer>(__ptr),
-        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
+        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0)));
 #      else
-    return iterator(__ptr);
+    return iterator(__wrap_iter<__pointer>(__ptr));
 #      endif
   }
 
@@ -740,12 +744,12 @@ public:
     auto* __ptr          = std::addressof(__derived_self.__get());
 
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return std::__make_bounded_iter(
+    return const_iterator(std::__make_bounded_iter(
         __wrap_iter<__const_pointer>(__ptr),
         __wrap_iter<__const_pointer>(__ptr),
-        __wrap_iter<__const_pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
+        __wrap_iter<__const_pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0)));
 #      else
-    return const_iterator(__ptr);
+    return const_iterator(__wrap_iter<__const_pointer>(__ptr));
 #      endif
   }
 
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
new file mode 100644
index 0000000000000..424367b4f10b2
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: generic-hardening
+// <optional>
+
+// template <class T> class optional::iterator;
+// template <class T> class optional::const_iterator;
+
+#include <optional>
+#include <type_traits>
+
+template <typename T>
+concept has_iterator_aliases = requires {
+  typename T::iterator;
+  typename T::const_iterator;
+};
+
+static_assert(has_iterator_aliases<std::optional<int>>);
+static_assert(has_iterator_aliases<std::optional<const int>>);
+static_assert(has_iterator_aliases<std::optional<int&>>);
+static_assert(has_iterator_aliases<std::optional<const int&>>);
+static_assert(!has_iterator_aliases<std::optional<int (&)[1]>>);
+static_assert(!has_iterator_aliases<std::optional<int (&)()>>);
+
+using Iter1 = std::optional<int>::iterator;
+using Iter2 = std::optional<double>::iterator;
+using Iter3 = std::optional<int>::const_iterator;
+using Iter4 = std::optional<double>::const_iterator;
+
+static_assert(std::is_convertible_v<Iter1, Iter1>);
+static_assert(!std::is_convertible_v<Iter1, Iter2>);
+static_assert(!std::is_convertible_v<Iter1, Iter3>);
+static_assert(!std::is_convertible_v<Iter1, Iter4>);
+
+static_assert(std::is_convertible_v<Iter2, Iter2>);
+static_assert(!std::is_convertible_v<Iter2, Iter1>);
+static_assert(!std::is_convertible_v<Iter2, Iter3>);
+static_assert(!std::is_convertible_v<Iter2, Iter4>);
+
+static_assert(std::is_convertible_v<Iter3, Iter3>);
+static_assert(!std::is_convertible_v<Iter3, Iter1>);
+static_assert(!std::is_convertible_v<Iter3, Iter2>);
+static_assert(!std::is_convertible_v<Iter3, Iter4>);
+
+static_assert(std::is_convertible_v<Iter4, Iter4>);
+static_assert(!std::is_convertible_v<Iter4, Iter1>);
+static_assert(!std::is_convertible_v<Iter4, Iter2>);
+static_assert(!std::is_convertible_v<Iter4, Iter3>);

>From a4d20157903b365900b942d2713a1ba5d1eaaead Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 18 Aug 2025 20:39:34 -0400
Subject: [PATCH 02/18] Update iterator tests

---
 .../iterator.compile.pass.cpp                 |  2 +-
 .../optional.iterator/iterator.pass.cpp       | 24 +++++
 .../iterator_compare.pass.cpp                 | 99 +++++++++++++++++++
 3 files changed, 124 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp

diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index 424367b4f10b2..442195bdcb948 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // REQUIRES: std-at-least-c++26
-// UNSUPPORTED: generic-hardening
+
 // <optional>
 
 // template <class T> class optional::iterator;
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
index 1be86305b449c..996811d078b86 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
@@ -98,6 +98,30 @@ constexpr void test(std::decay_t<T> v) {
     assert(val.begin() != val.end());
     assert(*(val.begin()) == v);
   }
+
+  // [container.reqmts] operator-
+  {
+    std::optional<T> val(v);
+    auto it1 = val.begin();
+    auto it2 = val.begin();
+    auto it3 = val.end();
+
+    auto cit1 = std::as_const(val).begin();
+    auto cit2 = std::as_const(val).begin();
+    auto cit3 = std::as_const(val).end();
+
+    assert(it1 - it2 == 0);
+    assert(cit1 - cit2 == 0);
+    assert(it1 - cit1 == 0);
+    assert(it3 - it1 == 1);
+    assert(it1 - it3 == -1);
+
+    assert(cit3 - cit1 == 1);
+    assert(cit1 - cit3 == -1);
+    assert(cit3 - cit3 == 0);
+    assert(cit3 - it1 == 1);
+    assert(it1 - cit3 == -1);
+  }
 }
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
new file mode 100644
index 0000000000000..16b74ade9d82e
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
@@ -0,0 +1,99 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <optional>
+
+// template <class T> class optional::iterator;
+// template <class T> class optional::const_iterator;
+
+#include <cassert>
+#include <compare>
+#include <concepts>
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+template<typename T>
+constexpr bool test() {
+  using Opt = std::optional<T>;
+  using I = Opt::iterator;
+  using CI = Opt::const_iterator;
+
+  static_assert(std::three_way_comparable<I>);
+  static_assert(std::three_way_comparable<CI>);
+
+  std::remove_reference_t<T> t{};
+  Opt opt{t};
+
+  // [container.reqmts] tests for comparison operators of optional::iterator and optional::const_iterator
+  auto it1 = opt.begin();
+
+  {
+    auto it2 = opt.begin();
+    assert(it1 == it2);
+    assert(!(it1 != it2));
+
+    static_assert(std::same_as<decltype(it1 <=> it2), std::strong_ordering>);
+    assert(it1 <=> it2 == std::strong_ordering::equal);
+  }
+
+  {
+    auto it3 = opt.end();
+    assert(it1 != it3);
+    assert(it1 <= it3);
+    assert(it1 < it3);
+    assert(it3 >= it1);
+    assert(it3 > it1);
+
+    assert(it1 <=> it3 == std::strong_ordering::less);
+    assert(it3 <=> it1 == std::strong_ordering::greater);
+  }
+
+  auto cit1 = std::as_const(opt).begin();
+
+  {
+    auto cit2 = std::as_const(opt).begin();
+    assert(cit1 == cit2);
+    assert(!(cit1 != cit2));
+
+    static_assert(std::same_as<decltype(cit1 <=> cit2), std::strong_ordering>);
+    assert(cit1 <=> cit2 == std::strong_ordering::equal);
+  }
+
+  {
+    auto cit3 = std::as_const(opt).end();
+
+    assert(cit1 <= cit3);
+    assert(cit1 < cit3);
+    assert(cit3 >= cit1);
+    assert(cit3 > cit1);
+
+    assert(cit1 <=> cit3 == std::strong_ordering::less);
+    assert(cit3 <=> cit1 == std::strong_ordering::greater);
+  }
+
+  return true;
+}
+
+
+constexpr bool test() {
+  test<int>();
+  test<char>();
+  test<int&>();
+
+  return true;
+}
+
+int main(int, char**) {
+  assert(test());
+  static_assert(test());
+
+  return 0;
+}

>From e02bec6d3278a79204fc31ce96f6ed9ddd0b02a1 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 2 Dec 2025 21:30:14 -0500
Subject: [PATCH 03/18] Formatting

---
 .../optional/optional.iterator/iterator_compare.pass.cpp   | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
index 16b74ade9d82e..958519d4c805c 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
@@ -20,11 +20,11 @@
 #include <type_traits>
 #include <utility>
 
-template<typename T>
+template <typename T>
 constexpr bool test() {
   using Opt = std::optional<T>;
-  using I = Opt::iterator;
-  using CI = Opt::const_iterator;
+  using I   = Opt::iterator;
+  using CI  = Opt::const_iterator;
 
   static_assert(std::three_way_comparable<I>);
   static_assert(std::three_way_comparable<CI>);
@@ -82,7 +82,6 @@ constexpr bool test() {
   return true;
 }
 
-
 constexpr bool test() {
   test<int>();
   test<char>();

>From 032cac20260c82917777cb4bd891f42a9119b510 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 4 Dec 2025 14:30:42 -0500
Subject: [PATCH 04/18] Allow conversions from iterator -> const_iterator

---
 libcxx/include/__iterator/upper_bounded_iterator.h       | 9 ++++++++-
 .../optional/optional.iterator/iterator.compile.pass.cpp | 4 ++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__iterator/upper_bounded_iterator.h b/libcxx/include/__iterator/upper_bounded_iterator.h
index 1ae0d11ce379f..8aa2a0340f7bc 100644
--- a/libcxx/include/__iterator/upper_bounded_iterator.h
+++ b/libcxx/include/__iterator/upper_bounded_iterator.h
@@ -11,7 +11,7 @@
  * __upper_bounded_iterator is an iterator that wraps an underlying iterator.
  * It stores the underlying container type to prevent mixing iterators, and allow algorithms
  * to optimize based on the underlying container type.
- * It also stores the absolute maximum amount of elements the container can have, known at compile-time.
+ * It also encodes the container's (known at compile-time) maximum amount of elements as part of the type.
  * As of writing, the only standard library containers which have this property are inplace_vector and optional.
  */
 
@@ -26,6 +26,7 @@
 #include <__iterator/iterator_traits.h>
 #include <__memory/pointer_traits.h>
 #include <__type_traits/is_constructible.h>
+#include <__type_traits/is_convertible.h>
 #include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -59,6 +60,12 @@ class __upper_bounded_iterator {
 
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __upper_bounded_iterator(_Iter __iter) : __iter_(std::move(__iter)) {}
 
+  template <typename _Iter2>
+    requires is_convertible_v<_Iter2, _Iter>
+  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator(
+      const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements>& __y)
+      : __iter_(__y.__iter_) {}
+
   _LIBCPP_HIDE_FROM_ABI constexpr _Iter __base() const noexcept(noexcept(_Iter(__iter_))) { return __iter_; }
   _LIBCPP_HIDE_FROM_ABI constexpr auto __max_elements() const noexcept { return _Max_Elements; }
 
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index 442195bdcb948..1d0009d3ed2d9 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -36,13 +36,13 @@ using Iter4 = std::optional<double>::const_iterator;
 
 static_assert(std::is_convertible_v<Iter1, Iter1>);
 static_assert(!std::is_convertible_v<Iter1, Iter2>);
-static_assert(!std::is_convertible_v<Iter1, Iter3>);
+static_assert(std::is_convertible_v<Iter1, Iter3>);
 static_assert(!std::is_convertible_v<Iter1, Iter4>);
 
 static_assert(std::is_convertible_v<Iter2, Iter2>);
 static_assert(!std::is_convertible_v<Iter2, Iter1>);
 static_assert(!std::is_convertible_v<Iter2, Iter3>);
-static_assert(!std::is_convertible_v<Iter2, Iter4>);
+static_assert(std::is_convertible_v<Iter2, Iter4>);
 
 static_assert(std::is_convertible_v<Iter3, Iter3>);
 static_assert(!std::is_convertible_v<Iter3, Iter1>);

>From 074e062ea79841ab2d4220c6e2b4a757024a619f Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 5 Dec 2025 18:38:09 -0500
Subject: [PATCH 05/18] Address most comments, try new name

---
 libcxx/include/CMakeLists.txt                 |   2 +-
 .../__iterator/capacity_aware_iterator.h      | 180 +++++++++++++++++
 .../__iterator/upper_bounded_iterator.h       | 181 ------------------
 libcxx/include/module.modulemap.in            |   2 +-
 libcxx/include/optional                       |   4 +-
 .../iterator.compile.pass.cpp                 |  19 +-
 6 files changed, 199 insertions(+), 189 deletions(-)
 create mode 100644 libcxx/include/__iterator/capacity_aware_iterator.h
 delete mode 100644 libcxx/include/__iterator/upper_bounded_iterator.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 5d804cca49677..04ca182007dc0 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -477,6 +477,7 @@ set(files
   __iterator/aliasing_iterator.h
   __iterator/back_insert_iterator.h
   __iterator/bounded_iter.h
+  __iterator/capacity_aware_iterator.h
   __iterator/common_iterator.h
   __iterator/concepts.h
   __iterator/counted_iterator.h
@@ -516,7 +517,6 @@ set(files
   __iterator/sortable.h
   __iterator/static_bounded_iter.h
   __iterator/unreachable_sentinel.h
-  __iterator/upper_bounded_iterator.h
   __iterator/wrap_iter.h
   __locale
   __locale_dir/check_grouping.h
diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
new file mode 100644
index 0000000000000..f006e773a39d0
--- /dev/null
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -0,0 +1,180 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+#define _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+
+#include <__assert>
+#include <__compare/ordering.h>
+#include <__compare/three_way_comparable.h>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/pointer_traits.h>
+#include <__type_traits/is_constructible.h>
+#include <__type_traits/is_convertible.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 26
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// __capacity_aware_iterator is an iterator that wraps an underlying iterator.
+// It stores the underlying container type to prevent mixing iterators, and allow algorithms
+// to optimize based on the underlying container type.
+// It also encodes the container's (known at compile-time) maximum amount of elements as part of the type.
+// As of writing, the only standard library containers which have this property are inplace_vector and optional.
+
+template <class _Iter, class _Container, std::size_t _ContainerMaxElements>
+class __capacity_aware_iterator {
+private:
+  _Iter __iter_;
+
+  friend _Container;
+
+public:
+  using iterator_category = iterator_traits<_Iter>::iterator_category;
+  using iterator_concept  = _Iter::iterator_concept;
+  using difference_type   = iter_difference_t<_Iter>;
+  using pointer           = iterator_traits<_Iter>::pointer;
+  using reference         = iter_reference_t<_Iter>;
+  using value_type        = iter_value_t<_Iter>;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator()
+    requires is_default_constructible_v<_Iter>
+  = default;
+
+  template <typename _Iter2>
+    requires is_convertible_v<_Iter2, _Iter>
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator(
+      const __capacity_aware_iterator<_Iter2, _Container, _ContainerMaxElements>& __y)
+      : __iter_(__y.base()) {}
+
+private:
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __capacity_aware_iterator(_Iter __iter) : __iter_(std::move(__iter)) {}
+
+  template <typename _Tp, class>
+  friend struct __optional_iterator;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() const noexcept { return __iter_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator->() const
+    requires requires { __iter_.operator->(); }
+  {
+    return __iter_.operator->();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator++() {
+    ++__iter_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator operator++(int) {
+    __capacity_aware_iterator __tmp(*this);
+    ++*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator--() {
+    --__iter_;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator operator--(int) {
+    __capacity_aware_iterator __tmp(*this);
+    --*this;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator+=(difference_type __n) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        (__n >= 0 ? __n : -__n) <= _ContainerMaxElements,
+        "__capacity_aware_iterator::operator+=: Attempting to move iterator past its "
+        "container's possible range");
+
+    __iter_ += __n;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator-=(difference_type __n) {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        (__n >= 0 ? __n : -__n) <= _ContainerMaxElements,
+        "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
+
+    __iter_ -= __n;
+    return *this;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+        (__n >= 0 ? __n : -__n) < _ContainerMaxElements,
+        "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+    return *(*this + __n);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr bool
+  operator==(const __capacity_aware_iterator& __x, const __capacity_aware_iterator& __y) {
+    return __x.__iter_ == __y.__iter_;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
+  operator<=>(const __capacity_aware_iterator& __x, const __capacity_aware_iterator& __y) {
+    if constexpr (three_way_comparable_with<_Iter, _Iter, strong_ordering>) {
+      return __x.__iter_ <=> __y.__iter_;
+    } else {
+      if (__x.__iter_ < __x.__iter_) {
+        return strong_ordering::less;
+      } else if (__x.__iter_ == __y.__iter_) {
+        return strong_ordering::equal;
+      }
+      return strong_ordering::greater;
+    }
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __capacity_aware_iterator
+  operator+(const __capacity_aware_iterator& __i, difference_type __n) {
+    auto __tmp = __i;
+    __tmp += __n;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __capacity_aware_iterator
+  operator+(difference_type __n, const __capacity_aware_iterator& __i) {
+    auto __tmp = __i;
+    __tmp += __n;
+    return __tmp;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr __capacity_aware_iterator
+  operator-(const __capacity_aware_iterator& __i, difference_type __n) {
+    return __i.__iter_ + __n;
+  }
+
+  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+  operator-(const __capacity_aware_iterator& __x, const __capacity_aware_iterator& __y) {
+    return difference_type(__x.base() - __y.base());
+  }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
diff --git a/libcxx/include/__iterator/upper_bounded_iterator.h b/libcxx/include/__iterator/upper_bounded_iterator.h
deleted file mode 100644
index 8aa2a0340f7bc..0000000000000
--- a/libcxx/include/__iterator/upper_bounded_iterator.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-/*
- * __upper_bounded_iterator is an iterator that wraps an underlying iterator.
- * It stores the underlying container type to prevent mixing iterators, and allow algorithms
- * to optimize based on the underlying container type.
- * It also encodes the container's (known at compile-time) maximum amount of elements as part of the type.
- * As of writing, the only standard library containers which have this property are inplace_vector and optional.
- */
-
-#ifndef _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
-#define _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
-
-#include <__compare/ordering.h>
-#include <__compare/three_way_comparable.h>
-#include <__config>
-#include <__cstddef/size_t.h>
-#include <__iterator/incrementable_traits.h>
-#include <__iterator/iterator_traits.h>
-#include <__memory/pointer_traits.h>
-#include <__type_traits/is_constructible.h>
-#include <__type_traits/is_convertible.h>
-#include <__utility/move.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
-#if _LIBCPP_STD_VER >= 26
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-template <class _Iter, class _Container, std::size_t _Max_Elements>
-class __upper_bounded_iterator {
-private:
-  _Iter __iter_;
-
-  friend _Container;
-
-public:
-  using iterator_category = iterator_traits<_Iter>::iterator_category;
-  using iterator_concept  = _Iter::iterator_concept;
-  using value_type        = iter_value_t<_Iter>;
-  using difference_type   = iter_difference_t<_Iter>;
-  using reference         = iter_reference_t<_Iter>;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator()
-    requires is_default_constructible_v<_Iter>
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __upper_bounded_iterator(_Iter __iter) : __iter_(std::move(__iter)) {}
-
-  template <typename _Iter2>
-    requires is_convertible_v<_Iter2, _Iter>
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator(
-      const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements>& __y)
-      : __iter_(__y.__iter_) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr _Iter __base() const noexcept(noexcept(_Iter(__iter_))) { return __iter_; }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto __max_elements() const noexcept { return _Max_Elements; }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; }
-  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator->() const
-    requires requires { __iter_.operator->(); }
-  {
-    return __iter_.operator->();
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator++() {
-    ++__iter_;
-    return *this;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator operator++(int) {
-    __upper_bounded_iterator __tmp(*this);
-    ++*this;
-    return __tmp;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator--() {
-    --__iter_;
-    return *this;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator operator--(int) {
-    __upper_bounded_iterator __tmp(*this);
-    --*this;
-    return __tmp;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator+=(difference_type __x) {
-    __iter_ += __x;
-    return *this;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __upper_bounded_iterator& operator-=(difference_type __x) {
-    __iter_ -= __x;
-    return *this;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const { return *(*this + __n); }
-
-  _LIBCPP_HIDE_FROM_ABI friend constexpr bool
-  operator==(const __upper_bounded_iterator& __x, const __upper_bounded_iterator& __y) {
-    return __x.__iter_ == __y.__iter_;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
-  operator<=>(const __upper_bounded_iterator& __x, const __upper_bounded_iterator& __y) {
-    if constexpr (three_way_comparable_with<_Iter, _Iter, strong_ordering>) {
-      return __x.__iter_ <=> __y.__iter_;
-    } else {
-      if (__x.__iter_ < __x.__iter_) {
-        return strong_ordering::less;
-      } else if (__x.__iter_ == __y.__iter_) {
-        return strong_ordering::equal;
-      }
-      return strong_ordering::greater;
-    }
-  }
-
-  template <class _Iter2>
-  _LIBCPP_HIDE_FROM_ABI friend constexpr auto
-  operator<=>(const __upper_bounded_iterator& __x,
-              const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements> __y) {
-    if constexpr (three_way_comparable_with<_Iter, _Iter2, strong_ordering>) {
-      return __x.__iter_ <=> __y.__iter_;
-    } else {
-      if (__x.__iter_ < __x.__iter_) {
-        return strong_ordering::less;
-      } else if (__x.__iter_ == __y.__iter_) {
-        return strong_ordering::equal;
-      }
-      return strong_ordering::greater;
-    }
-  }
-
-  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
-  operator+(const __upper_bounded_iterator& __i, difference_type __n) {
-    auto __tmp = __i;
-    __tmp += __n;
-    return __tmp;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
-  operator+(difference_type __n, const __upper_bounded_iterator& __i) {
-    auto __tmp = __i;
-    __tmp += __n;
-    return __tmp;
-  }
-
-  _LIBCPP_HIDE_FROM_ABI friend constexpr __upper_bounded_iterator
-  operator-(const __upper_bounded_iterator& __i, difference_type __n) {
-    return __i.__iter_ + __n;
-  }
-
-  template <class _Iter2>
-  _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
-  operator-(const __upper_bounded_iterator& __x,
-            const __upper_bounded_iterator<_Iter2, _Container, _Max_Elements>& __y) {
-    return difference_type(__x.__base() - __y.__base());
-  }
-};
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP_STD_VER >= 26
-
-_LIBCPP_POP_MACROS
-
-#endif // _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 54d16ea9fef3f..92df7c6a85e6c 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1544,7 +1544,7 @@ module std [system] {
     module sortable                   { header "__iterator/sortable.h" }
     module static_bounded_iter        { header "__iterator/static_bounded_iter.h" }
     module unreachable_sentinel       { header "__iterator/unreachable_sentinel.h" }
-    module upper_bounded_iterator     { header "__iterator/upper_bounded_iterator.h" }
+    module capacity_aware_iterator    { header "__iterator/capacity_aware_iterator.h" }
     module wrap_iter                  { header "__iterator/wrap_iter.h" }
 
     header "iterator"
diff --git a/libcxx/include/optional b/libcxx/include/optional
index efd5bbfe517de..2032869f9d466 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -271,7 +271,7 @@ namespace std {
 #  include <__functional/unary_function.h>
 #  include <__fwd/functional.h>
 #  include <__iterator/bounded_iter.h>
-#  include <__iterator/upper_bounded_iterator.h>
+#  include <__iterator/capacity_aware_iterator.h>
 #  include <__iterator/wrap_iter.h>
 #  include <__memory/addressof.h>
 #  include <__memory/construct_at.h>
@@ -713,7 +713,7 @@ private:
 
 #    if _LIBCPP_STD_VER >= 26
   template <typename _Underlying>
-  using __iter _LIBCPP_NODEBUG = __upper_bounded_iterator<_Underlying, __optional_iterator, 1>;
+  using __iter _LIBCPP_NODEBUG = __capacity_aware_iterator<_Underlying, optional<_Tp>, 1>;
 
 public:
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index 1d0009d3ed2d9..7db0c9ec32e87 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -15,6 +15,7 @@
 
 #include <optional>
 #include <type_traits>
+#include <vector>
 
 template <typename T>
 concept has_iterator_aliases = requires {
@@ -29,27 +30,37 @@ static_assert(has_iterator_aliases<std::optional<const int&>>);
 static_assert(!has_iterator_aliases<std::optional<int (&)[1]>>);
 static_assert(!has_iterator_aliases<std::optional<int (&)()>>);
 
-using Iter1 = std::optional<int>::iterator;
-using Iter2 = std::optional<double>::iterator;
-using Iter3 = std::optional<int>::const_iterator;
-using Iter4 = std::optional<double>::const_iterator;
+using Iter1  = std::optional<int>::iterator;
+using Iter2  = std::optional<double>::iterator;
+using Iter3  = std::optional<int>::const_iterator;
+using Iter4  = std::optional<double>::const_iterator;
+using VIter1 = std::vector<int>::iterator;
+using VIter2 = std::vector<int>::const_iterator;
 
 static_assert(std::is_convertible_v<Iter1, Iter1>);
 static_assert(!std::is_convertible_v<Iter1, Iter2>);
 static_assert(std::is_convertible_v<Iter1, Iter3>);
 static_assert(!std::is_convertible_v<Iter1, Iter4>);
+static_assert(!std::is_convertible_v<Iter1, VIter1>);
+static_assert(!std::is_convertible_v<Iter1, VIter2>);
 
 static_assert(std::is_convertible_v<Iter2, Iter2>);
 static_assert(!std::is_convertible_v<Iter2, Iter1>);
 static_assert(!std::is_convertible_v<Iter2, Iter3>);
 static_assert(std::is_convertible_v<Iter2, Iter4>);
+static_assert(!std::is_convertible_v<Iter2, VIter1>);
+static_assert(!std::is_convertible_v<Iter2, VIter2>);
 
 static_assert(std::is_convertible_v<Iter3, Iter3>);
 static_assert(!std::is_convertible_v<Iter3, Iter1>);
 static_assert(!std::is_convertible_v<Iter3, Iter2>);
 static_assert(!std::is_convertible_v<Iter3, Iter4>);
+static_assert(!std::is_convertible_v<Iter3, VIter1>);
+static_assert(!std::is_convertible_v<Iter3, VIter2>);
 
 static_assert(std::is_convertible_v<Iter4, Iter4>);
 static_assert(!std::is_convertible_v<Iter4, Iter1>);
 static_assert(!std::is_convertible_v<Iter4, Iter2>);
 static_assert(!std::is_convertible_v<Iter4, Iter3>);
+static_assert(!std::is_convertible_v<Iter4, VIter1>);
+static_assert(!std::is_convertible_v<Iter4, VIter2>);

>From 63c5f489e941dc08e755ae680c1ac05da3132794 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 5 Dec 2025 20:20:22 -0500
Subject: [PATCH 06/18] Don't wrap bounded_iter because there would a second
 redundant bounds check

---
 libcxx/include/optional | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 2032869f9d466..e586c4a4bca16 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -717,8 +717,8 @@ private:
 
 public:
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-  using iterator       = __iter<__bounded_iter<__wrap_iter<__pointer>>>;
-  using const_iterator = __iter<__bounded_iter<__wrap_iter<__const_pointer>>>;
+  using iterator       = __bounded_iter<__wrap_iter<__pointer>>;
+  using const_iterator = __bounded_iter<__wrap_iter<__const_pointer>>;
 #      else
   using iterator       = __iter<__wrap_iter<__pointer>>;
   using const_iterator = __iter<__wrap_iter<__const_pointer>>;
@@ -730,10 +730,10 @@ public:
     auto* __ptr          = std::addressof(__derived_self.__get());
 
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return iterator(std::__make_bounded_iter(
+    return std::__make_bounded_iter(
         __wrap_iter<__pointer>(__ptr),
         __wrap_iter<__pointer>(__ptr),
-        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0)));
+        __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
 #      else
     return iterator(__wrap_iter<__pointer>(__ptr));
 #      endif
@@ -744,10 +744,10 @@ public:
     auto* __ptr          = std::addressof(__derived_self.__get());
 
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return const_iterator(std::__make_bounded_iter(
+    return std::__make_bounded_iter(
         __wrap_iter<__const_pointer>(__ptr),
         __wrap_iter<__const_pointer>(__ptr),
-        __wrap_iter<__const_pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0)));
+        __wrap_iter<__const_pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
 #      else
     return const_iterator(__wrap_iter<__const_pointer>(__ptr));
 #      endif

>From 09c0a2128e305a7aa9426baea4c0592a7c6ab3ab Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 5 Dec 2025 20:18:38 -0500
Subject: [PATCH 07/18] Add iterator fail test

---
 .../assert.arithmetic.pass.cpp                | 46 +++++++++++++++++++
 .../iterator.compile.pass.cpp                 |  2 +
 .../iterator_compare.pass.cpp                 |  4 +-
 .../libcxx/test/features/libcxx_macros.py     |  1 +
 4 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp

diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
new file mode 100644
index 0000000000000..f66a3f5214343
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <optional>
+
+// Add to iterator out of bounds.
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none, libcpp-has-abi-bounded-iterators-in-optional
+
+#include <optional>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+  {
+    std::optional<int> opt(1);
+    auto i = opt.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += 2,
+        "__capacity_aware_iterator::operator+=: Attempting to advance iterator past its container's possible range");
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += -2, "__capacity_aware_iterator::operator+=: Attempting to rewind iterator past its container's start");
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= 2, "__capacity_aware_iterator::operator-=: Attempting to rewind iterator before its container's start");
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= -2,
+        "__capacity_aware_iterator::operator+=: Attempting to advance iterator past its container's possible range");
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[2],
+        "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[-2], "__capacity_aware_iterator::operator[]: Attempting to index iterator before its container's start");
+  }
+}
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index 7db0c9ec32e87..ea99978f72e7c 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -10,6 +10,8 @@
 
 // <optional>
 
+// UNSUPPORTED: libcpp-has-abi-bounded-iterators-in-optional
+
 // template <class T> class optional::iterator;
 // template <class T> class optional::const_iterator;
 
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
index 958519d4c805c..d24300931d566 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
@@ -10,8 +10,8 @@
 
 // <optional>
 
-// template <class T> class optional::iterator;
-// template <class T> class optional::const_iterator;
+// template <class T> class optional::iterator::operator<=>;
+// template <class T> class optional::const_iterator::operator<=>;
 
 #include <cassert>
 #include <compare>
diff --git a/libcxx/utils/libcxx/test/features/libcxx_macros.py b/libcxx/utils/libcxx/test/features/libcxx_macros.py
index 7a465f2e87866..71297e6a8880c 100644
--- a/libcxx/utils/libcxx/test/features/libcxx_macros.py
+++ b/libcxx/utils/libcxx/test/features/libcxx_macros.py
@@ -25,6 +25,7 @@
     "_LIBCPP_ABI_VERSION": "libcpp-abi-version",
     "_LIBCPP_ABI_BOUNDED_ITERATORS": "libcpp-has-abi-bounded-iterators",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING": "libcpp-has-abi-bounded-iterators-in-string",
+    "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL": "libcpp-has-abi-bounded-iterators-in-optional",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR": "libcpp-has-abi-bounded-iterators-in-vector",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY": "libcpp-has-abi-bounded-iterators-in-std-array",
     "_LIBCPP_ABI_BOUNDED_UNIQUE_PTR": "libcpp-has-abi-bounded-unique_ptr",

>From f79a016e948ef557007ad654253832f6965a2e6c Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 6 Dec 2025 00:44:58 -0500
Subject: [PATCH 08/18] Resolve signedness issue

---
 libcxx/include/__iterator/capacity_aware_iterator.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index f006e773a39d0..797172337b26b 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -103,7 +103,7 @@ class __capacity_aware_iterator {
 
   _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator+=(difference_type __n) {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
-        (__n >= 0 ? __n : -__n) <= _ContainerMaxElements,
+        static_cast<size_t>((__n >= 0 ? __n : -__n)) <= _ContainerMaxElements,
         "__capacity_aware_iterator::operator+=: Attempting to move iterator past its "
         "container's possible range");
 
@@ -113,7 +113,7 @@ class __capacity_aware_iterator {
 
   _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator-=(difference_type __n) {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
-        (__n >= 0 ? __n : -__n) <= _ContainerMaxElements,
+        static_cast<size_t>((__n >= 0 ? __n : -__n)) <= _ContainerMaxElements,
         "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
 
     __iter_ -= __n;

>From 01ec05d3717c5959abbf608f8f0c31ff59b3ebda Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 6 Dec 2025 00:45:32 -0500
Subject: [PATCH 09/18] Rename iterator_compare.pass.cpp

---
 .../{iterator_compare.pass.cpp => compare.pass.cpp}               | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename libcxx/test/std/utilities/optional/optional.iterator/{iterator_compare.pass.cpp => compare.pass.cpp} (100%)

diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
similarity index 100%
rename from libcxx/test/std/utilities/optional/optional.iterator/iterator_compare.pass.cpp
rename to libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp

>From b3c9b84eeb1990fcf4ec0723c39f08c8278af693 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sat, 6 Dec 2025 14:36:15 -0500
Subject: [PATCH 10/18] Signed issue x2

---
 libcxx/include/__iterator/capacity_aware_iterator.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index 797172337b26b..fb05892b8a1b7 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -122,7 +122,7 @@ class __capacity_aware_iterator {
 
   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
-        (__n >= 0 ? __n : -__n) < _ContainerMaxElements,
+        static_cast<size_t>(__n >= 0 ? __n : -__n) < _ContainerMaxElements,
         "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
     return *(*this + __n);
   }

>From 3bb2d8b17a602294834fe35841455a692a295a5a Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Dec 2025 19:40:49 -0500
Subject: [PATCH 11/18] Deduce iterator concept, add create method

---
 .../__iterator/capacity_aware_iterator.h      | 28 +++++++++++++++++--
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index fb05892b8a1b7..73f095e87d339 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -15,6 +15,7 @@
 #include <__compare/three_way_comparable.h>
 #include <__config>
 #include <__cstddef/size_t.h>
+#include <__iterator/concepts.h>
 #include <__iterator/incrementable_traits.h>
 #include <__iterator/iterator_traits.h>
 #include <__memory/pointer_traits.h>
@@ -46,9 +47,23 @@ class __capacity_aware_iterator {
 
   friend _Container;
 
+  _LIBCPP_HIDE_FROM_ABI static constexpr auto __get_iter_concept() {
+    if constexpr (contiguous_iterator<_Iter>) {
+      return contiguous_iterator_tag{};
+    } else if constexpr (random_access_iterator<_Iter>) {
+      return random_access_iterator_tag{};
+    } else if constexpr (bidirectional_iterator<_Iter>) {
+      return bidirectional_iterator_tag{};
+    } else if constexpr (forward_iterator<_Iter>) {
+      return forward_iterator_tag{};
+    } else {
+      return input_iterator_tag{};
+    }
+  }
+
 public:
   using iterator_category = iterator_traits<_Iter>::iterator_category;
-  using iterator_concept  = _Iter::iterator_concept;
+  using iterator_concept  = decltype(__get_iter_concept());
   using difference_type   = iter_difference_t<_Iter>;
   using pointer           = iterator_traits<_Iter>::pointer;
   using reference         = iter_reference_t<_Iter>;
@@ -70,6 +85,9 @@ class __capacity_aware_iterator {
   template <typename _Tp, class>
   friend struct __optional_iterator;
 
+  template <class _It, class _C, size_t _M>
+  friend auto __make_capacity_aware_iterator(_It __iter);
+
 public:
   _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() const noexcept { return __iter_; }
   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; }
@@ -104,8 +122,7 @@ class __capacity_aware_iterator {
   _LIBCPP_HIDE_FROM_ABI constexpr __capacity_aware_iterator& operator+=(difference_type __n) {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
         static_cast<size_t>((__n >= 0 ? __n : -__n)) <= _ContainerMaxElements,
-        "__capacity_aware_iterator::operator+=: Attempting to move iterator past its "
-        "container's possible range");
+        "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
 
     __iter_ += __n;
     return *this;
@@ -171,6 +188,11 @@ class __capacity_aware_iterator {
   }
 };
 
+template <class _It, class _C, size_t _M>
+auto __make_capacity_aware_iterator(_It __iter) {
+  return __capacity_aware_iterator<_It, _C, _M>(__iter);
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_STD_VER >= 26

>From 651795918662140488d892d5b3f03e5c80fe32fc Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Dec 2025 19:41:11 -0500
Subject: [PATCH 12/18] Add tests

---
 .../capacity_aware_iter/arithmetic.pass.cpp   | 132 ++++++++++++++++++
 .../capacity_aware_iter/assert.pass.cpp       |  63 +++++++++
 .../capacity_aware_iter/comparison.pass.cpp   |  91 ++++++++++++
 .../capacity_aware_iter/dereference.pass.cpp  |  62 ++++++++
 .../types.compile.pass.cpp                    |  30 ++++
 .../assert.arithmetic.pass.cpp                |  13 +-
 6 files changed, 386 insertions(+), 5 deletions(-)
 create mode 100644 libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
 create mode 100644 libcxx/test/libcxx/iterators/capacity_aware_iter/assert.pass.cpp
 create mode 100644 libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
 create mode 100644 libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
 create mode 100644 libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp

diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
new file mode 100644
index 0000000000000..16e7ea7a6369c
--- /dev/null
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
@@ -0,0 +1,132 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// template <class _Iterator, class _Container, class _ContainerMaxElements>
+// struct __capacity_aware_iterator;
+
+// Arithmetic operators
+
+#include <__iterator/capacity_aware_iterator.h>
+#include <cstddef>
+#include <iterator>
+
+#include "test_iterators.h"
+
+template <typename Iter>
+constexpr bool test() {
+  int arr[] = {1, 2, 3, 4, 5, 6};
+  constexpr size_t sz = std::size(arr);
+
+  using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
+
+  int* i = arr + 0;
+
+  // operator++()
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter& res = ++iter;
+
+    assert(&res == &iter);
+    assert(*iter == 2);
+  }
+
+  // operator++(int)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter res = iter++;
+
+    assert(*res == 1);
+    assert(*iter == 2);
+  }
+
+  // operator--()
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 1));
+    CapIter& res = --iter;
+
+    assert(&iter == &res);
+    assert(*iter == 1);
+  }
+
+  // operator--(int)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 1));
+    CapIter res = iter--;
+
+    assert(*res == 2);
+    assert(*iter == 1);
+  }
+
+  // operator+=(difference_type)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter& res = iter += 2;
+
+    assert(&iter == &res);
+    assert(*iter == 3);
+  }
+
+  // operator+(__capacity_aware_iterator, difference_type)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter res = iter + 2;
+
+    assert(*iter == 1);
+    assert(*res == 3);
+  }
+
+  // operator+(difference_type, __capacity_aware_iterator)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter res = 2 + iter;
+
+    assert(*iter == 1);
+    assert(*res == 3);
+  }
+
+  // operator-=(difference_type)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
+    CapIter& res = iter -= 2;
+
+    assert(&iter == &res);
+    assert(*iter == 1);
+  }
+
+  // operator-(__capacity_aware_iterator, difference_type)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
+    CapIter res = iter - 2;
+
+    assert(*iter == 3);
+    assert(*res == 1);
+  }
+
+  // operator-(__capacity_aware_iterator, __capacity_aware_iterator)
+  {
+    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter iter2 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
+    CapIter iter3 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 6));
+    std::ptrdiff_t res = iter2 - iter;
+    std::ptrdiff_t res2 = iter3 - iter;
+
+    assert(res == 2);
+    assert(res2 == 6);
+  }
+
+  return true;
+}
+
+int main(int, char**){
+  assert(test<cpp20_random_access_iterator<int*>>());
+  static_assert(test<cpp20_random_access_iterator<int*>>());
+
+  return 0;
+}
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/assert.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/assert.pass.cpp
new file mode 100644
index 0000000000000..e014bc7d640db
--- /dev/null
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/assert.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+
+// template <class _Iterator, class _Container, class _ContainerMaxElements>
+// struct __capacity_aware_iterator;
+
+// Check assert failure if advancing, rewinding or indexing iterator past _ContainerMaxElements
+
+#include <__iterator/capacity_aware_iterator.h>
+#include <iterator>
+
+#include "check_assertion.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <typename Iter>
+void test() {
+  int arr[] = {1, 2, 3, 4};
+
+  constexpr long sz = std::size(arr);
+
+  using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
+
+  CapIter it = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(arr));
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it += (sz + 1),
+      "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it += -(sz + 1),
+      "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it -= (sz + 1),
+      "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it -= -(sz + 1),
+      "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it[sz],
+      "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+
+  TEST_LIBCPP_ASSERT_FAILURE(
+      it[-sz],
+      "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+}
+
+int main(int, char**) {
+  test<cpp20_random_access_iterator<int*>>();
+
+  return 0;
+}
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
new file mode 100644
index 0000000000000..0cf0facc262f3
--- /dev/null
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// template <class _Iterator, class _Container, class _ContainerMaxElements>
+// struct __capacity_aware_iterator;
+
+// Comparison operators
+
+#include <__iterator/capacity_aware_iterator.h>
+#include <compare>
+#include <iterator>
+
+#include "test_iterators.h"
+
+template<typename Iter>
+constexpr bool test(){
+  int arr[] = {1,2,3,4};
+  constexpr long sz = std::size(arr);
+
+  using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
+
+  CapIter iter1 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(arr));
+  CapIter iter2 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(arr + 4));
+
+  // operator==
+  {
+    assert(iter1 == iter1);
+    assert(!(iter1 == iter2));
+  }
+
+  // operator!=
+  {
+    assert(iter1 != iter2);
+    assert(!(iter1 != iter1));
+  }
+
+  // operator<
+  {
+    assert(iter1 < iter2);
+    assert(!(iter1 < iter1));
+    assert(!(iter2 < iter1));
+  }
+
+  // operator<=
+  {
+    assert(iter1 <= iter2);
+    assert(iter1 <= iter1);
+    assert(!(iter2 <= iter1));
+  }
+
+  // operator>
+  {
+    assert(iter2 > iter1);
+    assert(!(iter1 > iter2));
+    assert(!(iter1 > iter1));
+  }
+
+  // operator>=
+  {
+    assert(iter2 >= iter1);
+    assert(iter1 >= iter1);
+    assert(!(iter1 >= iter2));
+  }
+
+  // operator <=>
+  {
+    std::same_as<std::strong_ordering> decltype(auto) r1 = iter1 <=> iter2;
+    assert(r1 == std::strong_ordering::less);
+
+    std::same_as<std::strong_ordering> decltype(auto) r2 = iter2 <=> iter1;
+    assert(r2 == std::strong_ordering::greater);
+
+    std::same_as<std::strong_ordering> decltype(auto) r3 = iter1 <=> iter1;
+    assert(r3 == std::strong_ordering::equal);
+    assert(r3 == std::strong_ordering::equivalent);
+  }
+
+  return true;
+}
+
+int main(int, char**){
+  assert(test<cpp20_random_access_iterator<int*>>());
+  // static_assert(test<cpp20_random_access_iterator<int*>>());
+}
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
new file mode 100644
index 0000000000000..1f3b273e7b5b2
--- /dev/null
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// template <class _Iterator, class _Container, class _ContainerMaxElements>
+// struct __capacity_aware_iterator;
+
+// Dereference operators
+
+#include <__iterator/capacity_aware_iterator.h>
+
+#include "test_iterators.h"
+
+struct Foo {
+  int x;
+  constexpr bool operator==(Foo const& other) const { return x == other.x; }
+};
+
+template <typename Iter>
+constexpr bool test() {
+  Foo arr[]         = {Foo{1}, Foo{2}, Foo{3}, Foo{4}};
+  constexpr long sz = std::size(arr);
+
+  using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
+
+  CapIter it = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(arr));
+
+  // operator[]
+  {
+    assert(it[0] == Foo{1});
+    assert(it[1] == Foo{2});
+    assert(it[2] == Foo{3});
+
+    CapIter it2 = it + 2;
+
+    assert(it2[-1] == Foo{2});
+    assert(it2[-2] == Foo{1});
+  }
+
+  // operator*
+  {
+    assert(*it == Foo{1});
+  }
+
+  // operator->
+  {
+    assert(it->x == 1);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  assert(test<three_way_contiguous_iterator<Foo*>>());
+  static_assert(test<three_way_contiguous_iterator<Foo*>>());
+}
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp
new file mode 100644
index 0000000000000..ca7026000eb95
--- /dev/null
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// template <class _Iterator, class _Container, class _ContainerMaxElements>
+// struct __capacity_aware_iterator;
+
+// Nested types
+
+#include "test_iterators.h"
+#include <__iterator/capacity_aware_iterator.h>
+#include <iterator>
+#include <type_traits>
+
+using It = contiguous_iterator<int*>;
+
+using CapIter = std::__capacity_aware_iterator<It, int[], 1>;
+
+static_assert(std::is_same_v<CapIter::iterator_category, It::iterator_category>);
+static_assert(std::is_same_v<CapIter::iterator_concept, std::contiguous_iterator_tag>);
+static_assert(std::is_same_v<CapIter::difference_type, std::iter_difference_t<It>>);
+static_assert(std::is_same_v<CapIter::reference, std::iter_reference_t<It>>);
+static_assert(std::is_same_v<CapIter::reference, std::iter_reference_t<It>>);
+static_assert(std::is_same_v<CapIter::value_type, std::iter_value_t<It>>);
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
index f66a3f5214343..e40b269ee8255 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
@@ -24,23 +24,26 @@ int main(int, char**) {
 
     TEST_LIBCPP_ASSERT_FAILURE(
         i += 2,
-        "__capacity_aware_iterator::operator+=: Attempting to advance iterator past its container's possible range");
+        "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
 
     TEST_LIBCPP_ASSERT_FAILURE(
-        i += -2, "__capacity_aware_iterator::operator+=: Attempting to rewind iterator past its container's start");
+        i += -2,
+        "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
 
     TEST_LIBCPP_ASSERT_FAILURE(
-        i -= 2, "__capacity_aware_iterator::operator-=: Attempting to rewind iterator before its container's start");
+        i -= 2,
+        "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
 
     TEST_LIBCPP_ASSERT_FAILURE(
         i -= -2,
-        "__capacity_aware_iterator::operator+=: Attempting to advance iterator past its container's possible range");
+        "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
 
     TEST_LIBCPP_ASSERT_FAILURE(
         i[2],
         "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
 
     TEST_LIBCPP_ASSERT_FAILURE(
-        i[-2], "__capacity_aware_iterator::operator[]: Attempting to index iterator before its container's start");
+        i[-2],
+        "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
   }
 }

>From 965e9219bd10ab3d70bac9bb31f12610565fef47 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Dec 2025 20:46:45 -0500
Subject: [PATCH 13/18] Fix some typos

---
 .../include/__iterator/capacity_aware_iterator.h | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index 73f095e87d339..e5a8a9f788296 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -85,8 +85,8 @@ class __capacity_aware_iterator {
   template <typename _Tp, class>
   friend struct __optional_iterator;
 
-  template <class _It, class _C, size_t _M>
-  friend auto __make_capacity_aware_iterator(_It __iter);
+  template <class _It, class _Container2, size_t _ContainerMaxElems2>
+  _LIBCPP_HIDE_FROM_ABI friend constexpr auto __make_capacity_aware_iterator(_It __iter);
 
 public:
   _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() const noexcept { return __iter_; }
@@ -154,7 +154,7 @@ class __capacity_aware_iterator {
     if constexpr (three_way_comparable_with<_Iter, _Iter, strong_ordering>) {
       return __x.__iter_ <=> __y.__iter_;
     } else {
-      if (__x.__iter_ < __x.__iter_) {
+      if (__x.__iter_ < __y.__iter_) {
         return strong_ordering::less;
       } else if (__x.__iter_ == __y.__iter_) {
         return strong_ordering::equal;
@@ -179,7 +179,9 @@ class __capacity_aware_iterator {
 
   _LIBCPP_HIDE_FROM_ABI friend constexpr __capacity_aware_iterator
   operator-(const __capacity_aware_iterator& __i, difference_type __n) {
-    return __i.__iter_ + __n;
+    auto __tmp = __i;
+    __tmp -= __n;
+    return __tmp;
   }
 
   _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
@@ -188,9 +190,9 @@ class __capacity_aware_iterator {
   }
 };
 
-template <class _It, class _C, size_t _M>
-auto __make_capacity_aware_iterator(_It __iter) {
-  return __capacity_aware_iterator<_It, _C, _M>(__iter);
+template <class _It, class _Container2, size_t _ContainerMaxElems2>
+_LIBCPP_HIDE_FROM_ABI constexpr auto __make_capacity_aware_iterator(_It __iter) {
+  return __capacity_aware_iterator<_It, _Container2, _ContainerMaxElems2>(__iter);
 }
 
 _LIBCPP_END_NAMESPACE_STD

>From cc878ec37b4536613e76ca6e2ecd806d44f71707 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Dec 2025 21:22:45 -0500
Subject: [PATCH 14/18] Formatting

---
 .../capacity_aware_iter/arithmetic.pass.cpp   | 22 +++++++++----------
 .../capacity_aware_iter/comparison.pass.cpp   |  8 +++----
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
index 16e7ea7a6369c..26dbfa0d7be93 100644
--- a/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/arithmetic.pass.cpp
@@ -21,7 +21,7 @@
 
 template <typename Iter>
 constexpr bool test() {
-  int arr[] = {1, 2, 3, 4, 5, 6};
+  int arr[]           = {1, 2, 3, 4, 5, 6};
   constexpr size_t sz = std::size(arr);
 
   using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
@@ -40,7 +40,7 @@ constexpr bool test() {
   // operator++(int)
   {
     CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
-    CapIter res = iter++;
+    CapIter res  = iter++;
 
     assert(*res == 1);
     assert(*iter == 2);
@@ -58,7 +58,7 @@ constexpr bool test() {
   // operator--(int)
   {
     CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 1));
-    CapIter res = iter--;
+    CapIter res  = iter--;
 
     assert(*res == 2);
     assert(*iter == 1);
@@ -76,7 +76,7 @@ constexpr bool test() {
   // operator+(__capacity_aware_iterator, difference_type)
   {
     CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
-    CapIter res = iter + 2;
+    CapIter res  = iter + 2;
 
     assert(*iter == 1);
     assert(*res == 3);
@@ -85,7 +85,7 @@ constexpr bool test() {
   // operator+(difference_type, __capacity_aware_iterator)
   {
     CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
-    CapIter res = 2 + iter;
+    CapIter res  = 2 + iter;
 
     assert(*iter == 1);
     assert(*res == 3);
@@ -103,7 +103,7 @@ constexpr bool test() {
   // operator-(__capacity_aware_iterator, difference_type)
   {
     CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
-    CapIter res = iter - 2;
+    CapIter res  = iter - 2;
 
     assert(*iter == 3);
     assert(*res == 1);
@@ -111,10 +111,10 @@ constexpr bool test() {
 
   // operator-(__capacity_aware_iterator, __capacity_aware_iterator)
   {
-    CapIter iter = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
-    CapIter iter2 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
-    CapIter iter3 = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 6));
-    std::ptrdiff_t res = iter2 - iter;
+    CapIter iter        = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i));
+    CapIter iter2       = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 2));
+    CapIter iter3       = std::__make_capacity_aware_iterator<Iter, decltype(arr), sz>(Iter(i + 6));
+    std::ptrdiff_t res  = iter2 - iter;
     std::ptrdiff_t res2 = iter3 - iter;
 
     assert(res == 2);
@@ -124,7 +124,7 @@ constexpr bool test() {
   return true;
 }
 
-int main(int, char**){
+int main(int, char**) {
   assert(test<cpp20_random_access_iterator<int*>>());
   static_assert(test<cpp20_random_access_iterator<int*>>());
 
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
index 0cf0facc262f3..15ed12fe1b57a 100644
--- a/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
@@ -19,9 +19,9 @@
 
 #include "test_iterators.h"
 
-template<typename Iter>
-constexpr bool test(){
-  int arr[] = {1,2,3,4};
+template <typename Iter>
+constexpr bool test() {
+  int arr[]         = {1, 2, 3, 4};
   constexpr long sz = std::size(arr);
 
   using CapIter = std::__capacity_aware_iterator<Iter, decltype(arr), sz>;
@@ -85,7 +85,7 @@ constexpr bool test(){
   return true;
 }
 
-int main(int, char**){
+int main(int, char**) {
   assert(test<cpp20_random_access_iterator<int*>>());
   // static_assert(test<cpp20_random_access_iterator<int*>>());
 }

>From da5678185999cc942ba95bba16d1928c680c56b4 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 8 Dec 2025 22:35:25 -0500
Subject: [PATCH 15/18] Move include

---
 .../iterators/capacity_aware_iter/types.compile.pass.cpp       | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp
index ca7026000eb95..b3b72a0728ed7 100644
--- a/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/types.compile.pass.cpp
@@ -13,11 +13,12 @@
 
 // Nested types
 
-#include "test_iterators.h"
 #include <__iterator/capacity_aware_iterator.h>
 #include <iterator>
 #include <type_traits>
 
+#include "test_iterators.h"
+
 using It = contiguous_iterator<int*>;
 
 using CapIter = std::__capacity_aware_iterator<It, int[], 1>;

>From 123ee684a930ce1ff87589743e1da2a21b257875 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 9 Dec 2025 17:13:49 -0500
Subject: [PATCH 16/18] Other overlooked things

---
 libcxx/include/__iterator/capacity_aware_iterator.h         | 6 +++---
 .../iterators/capacity_aware_iter/comparison.pass.cpp       | 4 +++-
 .../iterators/capacity_aware_iter/dereference.pass.cpp      | 2 ++
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index e5a8a9f788296..3a5d0fb199c08 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
-#define _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+#ifndef _LIBCPP_CAPACITY_AWARE_ITERATOR_H
+#define _LIBCPP_CAPACITY_AWARE_ITERATOR_H
 
 #include <__assert>
 #include <__compare/ordering.h>
@@ -201,4 +201,4 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
 
-#endif // _LIBCPP___ITERATOR_UPPER_BOUNDED_ITERATOR_H
+#endif // _LIBCPP_CAPACITY_AWARE_ITERATOR_H
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
index 15ed12fe1b57a..67d236fc0d9ab 100644
--- a/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/comparison.pass.cpp
@@ -87,5 +87,7 @@ constexpr bool test() {
 
 int main(int, char**) {
   assert(test<cpp20_random_access_iterator<int*>>());
-  // static_assert(test<cpp20_random_access_iterator<int*>>());
+  static_assert(test<cpp20_random_access_iterator<int*>>());
+
+  return 0;
 }
diff --git a/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp b/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
index 1f3b273e7b5b2..34d7aa4983a27 100644
--- a/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
+++ b/libcxx/test/libcxx/iterators/capacity_aware_iter/dereference.pass.cpp
@@ -59,4 +59,6 @@ constexpr bool test() {
 int main(int, char**) {
   assert(test<three_way_contiguous_iterator<Foo*>>());
   static_assert(test<three_way_contiguous_iterator<Foo*>>());
+
+  return 0;
 }

>From ba73e83c82691384f27eb017f4a93994fb35fddc Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 9 Dec 2025 17:14:44 -0500
Subject: [PATCH 17/18] Macro formatting

---
 libcxx/include/__iterator/capacity_aware_iterator.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__iterator/capacity_aware_iterator.h b/libcxx/include/__iterator/capacity_aware_iterator.h
index 3a5d0fb199c08..53f72fac23876 100644
--- a/libcxx/include/__iterator/capacity_aware_iterator.h
+++ b/libcxx/include/__iterator/capacity_aware_iterator.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef _LIBCPP_CAPACITY_AWARE_ITERATOR_H
-#define _LIBCPP_CAPACITY_AWARE_ITERATOR_H
+#ifndef _LIBCPP___CAPACITY_AWARE_ITERATOR_H
+#define _LIBCPP___CAPACITY_AWARE_ITERATOR_H
 
 #include <__assert>
 #include <__compare/ordering.h>
@@ -201,4 +201,4 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
 
-#endif // _LIBCPP_CAPACITY_AWARE_ITERATOR_H
+#endif // _LIBCPP___CAPACITY_AWARE_ITERATOR_H

>From ee1c575bb866b21630aba2a430103f771a489d55 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 7 Jan 2026 22:03:06 -0500
Subject: [PATCH 18/18] Fix merge issues

---
 libcxx/include/optional                             |  8 +++++---
 .../optional.iterator/iterator.compile.pass.cpp     | 13 -------------
 .../optional/optional.iterator/compare.pass.cpp     |  9 +++++----
 3 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index e586c4a4bca16..d42c6455b9452 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -711,7 +711,6 @@ private:
   using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
 
-#    if _LIBCPP_STD_VER >= 26
   template <typename _Underlying>
   using __iter _LIBCPP_NODEBUG = __capacity_aware_iterator<_Underlying, optional<_Tp>, 1>;
 
@@ -764,13 +763,16 @@ public:
 template <class _Tp>
 struct __optional_iterator<_Tp&, enable_if_t<is_object_v<_Tp> && !__is_unbounded_array_v<_Tp> >> {
 private:
+  template <typename _Underlying>
+  using __iter _LIBCPP_NODEBUG = __capacity_aware_iterator<_Underlying, optional<_Tp&>, 1>;
+
   using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
 
 public:
 #      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
   using iterator = __bounded_iter<__wrap_iter<__pointer>>;
 #      else
-  using iterator = __wrap_iter<__pointer>;
+  using iterator = __iter<__wrap_iter<__pointer>>;
 #      endif
 
   // [optional.ref.iterators], iterator support
@@ -785,7 +787,7 @@ public:
         __wrap_iter<__pointer>(__ptr),
         __wrap_iter<__pointer>(__ptr) + (__derived_self.has_value() ? 1 : 0));
 #      else
-    return iterator(__ptr);
+    return iterator(__wrap_iter<__pointer>(__ptr));
 #      endif
   }
 
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index ea99978f72e7c..b6e407dacca42 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -19,19 +19,6 @@
 #include <type_traits>
 #include <vector>
 
-template <typename T>
-concept has_iterator_aliases = requires {
-  typename T::iterator;
-  typename T::const_iterator;
-};
-
-static_assert(has_iterator_aliases<std::optional<int>>);
-static_assert(has_iterator_aliases<std::optional<const int>>);
-static_assert(has_iterator_aliases<std::optional<int&>>);
-static_assert(has_iterator_aliases<std::optional<const int&>>);
-static_assert(!has_iterator_aliases<std::optional<int (&)[1]>>);
-static_assert(!has_iterator_aliases<std::optional<int (&)()>>);
-
 using Iter1  = std::optional<int>::iterator;
 using Iter2  = std::optional<double>::iterator;
 using Iter3  = std::optional<int>::const_iterator;
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
index d24300931d566..2c27ecb4c9f7c 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
@@ -23,11 +23,12 @@
 template <typename T>
 constexpr bool test() {
   using Opt = std::optional<T>;
-  using I   = Opt::iterator;
-  using CI  = Opt::const_iterator;
 
-  static_assert(std::three_way_comparable<I>);
-  static_assert(std::three_way_comparable<CI>);
+  static_assert(std::three_way_comparable<typename Opt::iterator>);
+
+  if constexpr (std::is_object_v<T>) {
+    static_assert(std::three_way_comparable<typename Opt::const_iterator>);
+  }
 
   std::remove_reference_t<T> t{};
   Opt opt{t};



More information about the libcxx-commits mailing list