[libcxx-commits] [libcxx] [libc++] Ensure that `std::expected` has no tail padding (PR #69673)

Jan Kokemüller via libcxx-commits libcxx-commits at lists.llvm.org
Thu Nov 2 12:54:13 PDT 2023


https://github.com/jiixyj updated https://github.com/llvm/llvm-project/pull/69673

>From 487bb665b324e79df5e6c2b793510bead826b849 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sun, 15 Oct 2023 22:09:51 +0200
Subject: [PATCH 01/31] ensure that expected has no tail padding

---
 libcxx/include/__expected/expected.h | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index bf16c8f720d2681..8475075e1557dfd 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -18,6 +18,7 @@
 #include <__memory/addressof.h>
 #include <__memory/construct_at.h>
 #include <__type_traits/conjunction.h>
+#include <__type_traits/datasizeof.h>
 #include <__type_traits/disjunction.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_assignable.h>
@@ -942,8 +943,17 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
+  _LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
+    struct __calc_expected {
+      _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
+      bool __has_val_;
+    };
+    return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
+  }
+
   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
   bool __has_val_;
+  char __padding_[__calculate_padding()]{};
 };
 
 template <class _Tp, class _Err>
@@ -1539,8 +1549,18 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
+    struct __calc_expected {
+      _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
+      bool __has_val_;
+    };
+    return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
+  }
+
   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
   bool __has_val_;
+  char __padding_[__calculate_padding()]{};
 };
 
 _LIBCPP_END_NAMESPACE_STD

>From 1da93c75595a6fac31a5271d01da1fb5c6126829 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Fri, 20 Oct 2023 19:40:18 +0200
Subject: [PATCH 02/31] handle GCC's warning in __libcpp_datasizeof

---
 libcxx/include/__type_traits/datasizeof.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/include/__type_traits/datasizeof.h b/libcxx/include/__type_traits/datasizeof.h
index 5688e3293a69eb5..96404ad15a73376 100644
--- a/libcxx/include/__type_traits/datasizeof.h
+++ b/libcxx/include/__type_traits/datasizeof.h
@@ -51,6 +51,7 @@ struct __libcpp_datasizeof {
   // the use as an extension.
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
+  _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
   static const size_t value = offsetof(_FirstPaddingByte<>, __first_padding_byte_);
   _LIBCPP_DIAGNOSTIC_POP
 };

>From d183218326d217ef8d22d010404ccd2a1ae41511 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Fri, 20 Oct 2023 19:53:22 +0200
Subject: [PATCH 03/31] implement different approach to padding calculation

This tries to fix two issues:

- There should be no artificial padding if the parameter type(s) don't
  need it, for example if they have no tail padding
- Prevent the padding array being zero length
---
 libcxx/include/__expected/expected.h | 53 +++++++++++++++++-----------
 1 file changed, 32 insertions(+), 21 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 8475075e1557dfd..3b1ae3c40df62d8 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -89,6 +89,34 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
+template <size_t __Padding>
+struct __expected_padding {
+  using type = char[__Padding];
+};
+
+template <>
+struct __expected_padding<0> {
+  using type = struct {};
+};
+
+template <class _Union>
+_LIBCPP_HIDE_FROM_ABI constexpr size_t __expected_calculate_padding() {
+  struct __calc_expected {
+    _LIBCPP_NO_UNIQUE_ADDRESS _Union __union_;
+    bool __has_val_;
+  };
+
+  size_t __datasize = __libcpp_datasizeof<__calc_expected>::value;
+  return sizeof(_Union) < __datasize ? 0 : sizeof(_Union) - __datasize;
+}
+
+// An object of this type must be the last member of the `expected` class to
+// ensure `expected`'s datasize is large enough to fit the parameter type(s).
+// It should be value-initialized so it is safe to copy when `expected`'s
+// copy operators are invoked.
+template <typename _Union>
+using __expected_padding_t = __expected_padding<__expected_calculate_padding<_Union>()>::type;
+
 template <class _Tp, class _Err>
 class expected {
   static_assert(
@@ -943,17 +971,9 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  _LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
-    struct __calc_expected {
-      _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
-      bool __has_val_;
-    };
-    return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
-  }
-
   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
-  bool __has_val_;
-  char __padding_[__calculate_padding()]{};
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_padding_t<__union_t<_Tp, _Err>> __padding_{};
 };
 
 template <class _Tp, class _Err>
@@ -1549,18 +1569,9 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-
-  _LIBCPP_HIDE_FROM_ABI static constexpr auto __calculate_padding() {
-    struct __calc_expected {
-      _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
-      bool __has_val_;
-    };
-    return sizeof(__calc_expected) - __libcpp_datasizeof<__calc_expected>::value;
-  }
-
   _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
-  bool __has_val_;
-  char __padding_[__calculate_padding()]{};
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_padding_t<__union_t<_Err>> __padding_{};
 };
 
 _LIBCPP_END_NAMESPACE_STD

>From 206079f77cbf30bfc7ae6f41c573e188f36deb8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Fri, 20 Oct 2023 19:56:59 +0200
Subject: [PATCH 04/31] add tests

---
 .../no_unique_address.compile.pass.cpp          | 17 +++++++++++++++++
 .../no_unique_address.compile.pass.cpp          | 15 +++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index c8c217054ae6c43..06f597d54871ee1 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -26,6 +26,13 @@ struct B : public A {
   virtual ~B() = default;
 };
 
+struct BoolWithPadding {
+  explicit operator bool() { return b; }
+
+private:
+  alignas(1024) bool b = false;
+};
+
 static_assert(sizeof(std::expected<Empty, Empty>) == sizeof(bool));
 static_assert(sizeof(std::expected<Empty, A>) == 2 * sizeof(int) + alignof(std::expected<Empty, A>));
 static_assert(sizeof(std::expected<Empty, B>) == sizeof(B) + alignof(std::expected<Empty, B>));
@@ -33,3 +40,13 @@ static_assert(sizeof(std::expected<A, Empty>) == 2 * sizeof(int) + alignof(std::
 static_assert(sizeof(std::expected<A, A>) == 2 * sizeof(int) + alignof(std::expected<A, A>));
 static_assert(sizeof(std::expected<B, Empty>) == sizeof(B) + alignof(std::expected<B, Empty>));
 static_assert(sizeof(std::expected<B, B>) == sizeof(B) + alignof(std::expected<B, B>));
+
+// Check that `expected`'s datasize is large enough for the parameter type(s).
+static_assert(sizeof(std::expected<BoolWithPadding, Empty>) ==
+              std::__libcpp_datasizeof<std::expected<BoolWithPadding, Empty>>::value);
+static_assert(sizeof(std::expected<Empty, BoolWithPadding>) ==
+              std::__libcpp_datasizeof<std::expected<Empty, BoolWithPadding>>::value);
+
+// In this case, there should be tail padding in the `expected` because `A`
+// itself does _not_ have tail padding.
+static_assert(sizeof(std::expected<A, A>) > std::__libcpp_datasizeof<std::expected<A, A>>::value);
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index dc59a6228386bcd..29cf8dff0d2b288 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -26,6 +26,21 @@ struct B : public A {
   virtual ~B() = default;
 };
 
+struct BoolWithPadding {
+  explicit operator bool() { return b; }
+
+private:
+  alignas(1024) bool b = false;
+};
+
 static_assert(sizeof(std::expected<void, Empty>) == sizeof(bool));
 static_assert(sizeof(std::expected<void, A>) == 2 * sizeof(int) + alignof(std::expected<void, A>));
 static_assert(sizeof(std::expected<void, B>) == sizeof(B) + alignof(std::expected<void, B>));
+
+// Check that `expected`'s datasize is large enough for the parameter type(s).
+static_assert(sizeof(std::expected<void, BoolWithPadding>) ==
+              std::__libcpp_datasizeof<std::expected<void, BoolWithPadding>>::value);
+
+// In this case, there should be tail padding in the `expected` because `A`
+// itself does _not_ have tail padding.
+static_assert(sizeof(std::expected<void, A>) > std::__libcpp_datasizeof<std::expected<void, A>>::value);

>From 4123459bf2df3ce056d8dbf5a055404601ed9b22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Fri, 20 Oct 2023 22:02:20 +0200
Subject: [PATCH 05/31] implement repr/compact_pair approach

---
 libcxx/include/__expected/expected.h          | 443 +++++++++---------
 .../no_unique_address.compile.pass.cpp        |   1 +
 .../no_unique_address.compile.pass.cpp        |   1 +
 3 files changed, 212 insertions(+), 233 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 3b1ae3c40df62d8..ab7cae1c1007f24 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -89,33 +89,11 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-template <size_t __Padding>
-struct __expected_padding {
-  using type = char[__Padding];
-};
-
-template <>
-struct __expected_padding<0> {
-  using type = struct {};
-};
-
 template <class _Union>
-_LIBCPP_HIDE_FROM_ABI constexpr size_t __expected_calculate_padding() {
-  struct __calc_expected {
-    _LIBCPP_NO_UNIQUE_ADDRESS _Union __union_;
-    bool __has_val_;
-  };
-
-  size_t __datasize = __libcpp_datasizeof<__calc_expected>::value;
-  return sizeof(_Union) < __datasize ? 0 : sizeof(_Union) - __datasize;
-}
-
-// An object of this type must be the last member of the `expected` class to
-// ensure `expected`'s datasize is large enough to fit the parameter type(s).
-// It should be value-initialized so it is safe to copy when `expected`'s
-// copy operators are invoked.
-template <typename _Union>
-using __expected_padding_t = __expected_padding<__expected_calculate_padding<_Union>()>::type;
+struct __expected_repr {
+    [[no_unique_address]] _Union __union_;
+    [[no_unique_address]] bool __has_val_;
+};
 
 template <class _Tp, class _Err>
 class expected {
@@ -148,7 +126,7 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr expected()
     noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
     requires is_default_constructible_v<_Tp>
-      : __union_(std::in_place), __has_val_(true) {}
+      : __repr_{.__union_{std::in_place}, .__has_val_ = true} {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -163,7 +141,7 @@ class expected {
     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
-      : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) { }
+      : __repr_{.__union_{__other.__repr_.__has_val_, __other.__repr_.__union_}, .__has_val_ = __other.__repr_.__has_val_} { }
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
@@ -174,7 +152,8 @@ class expected {
     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
-      : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) { }
+      : __repr_{.__union_{__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)},
+                .__has_val_ = __other.__repr_.__has_val_} { }
 
 private:
   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
@@ -199,12 +178,12 @@ class expected {
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(true) {}
+      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = true} {}
 
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
 public:
   template <class _Up, class _OtherErr>
@@ -214,14 +193,16 @@ class expected {
   expected(const expected<_Up, _OtherErr>& __other)
     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __union_(__other.__has_val_, __other.__union_), __has_val_(__other.__has_val_) {}
+      : __repr_{.__union_{__other.__repr_.__has_val_, __other.__repr_.__union_},
+                .__has_val_ = __other.__repr_.__has_val_} {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __other)
     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __union_(__other.__has_val_, std::move(__other.__union_)), __has_val_(__other.__has_val_) {}
+      : __repr_{.__union_{__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)},
+                .__has_val_ = __other.__repr_.__has_val_} {}
 
   template <class _Up = _Tp>
     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
@@ -229,47 +210,47 @@ class expected {
              (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
       expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
-      : __union_(std::in_place, std::forward<_Up>(__u)), __has_val_(true) {}
+      : __repr_{.__union_{std::in_place, std::forward<_Up>(__u)}, .__has_val_ = true} {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __union_(std::unexpect, __unex.error()), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, __unex.error()}, .__has_val_ = false} {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, std::move(__unex.error())}, .__has_val_ = false} {}
 
   template <class... _Args>
     requires is_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
-      : __union_(std::in_place, std::forward<_Args>(__args)...), __has_val_(true) {}
+      : __repr_{.__union_{std::in_place, std::forward<_Args>(__args)...}, .__has_val_ = true} {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
-      : __union_(std::in_place, __il, std::forward<_Args>(__args)...), __has_val_(true) {}
+      : __repr_{.__union_{std::in_place, __il, std::forward<_Args>(__args)...}, .__has_val_ = true} {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, __il, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
   // [expected.object.dtor], destructor
 
@@ -280,10 +261,10 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
     requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
   {
-    if (__has_val_) {
-      std::destroy_at(std::addressof(__union_.__val_));
+    if (__repr_.__has_val_) {
+      std::destroy_at(std::addressof(__repr_.__union_.__val_));
     } else {
-      std::destroy_at(std::addressof(__union_.__unex_));
+      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
     }
   }
 
@@ -327,17 +308,17 @@ class expected {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__has_val_ && __rhs.__has_val_) {
-      __union_.__val_ = __rhs.__union_.__val_;
-    } else if (__has_val_) {
-      __reinit_expected(__union_.__unex_, __union_.__val_, __rhs.__union_.__unex_);
-    } else if (__rhs.__has_val_) {
-      __reinit_expected(__union_.__val_, __union_.__unex_, __rhs.__union_.__val_);
+    if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
+      __repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
+    } else if (__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
+    } else if (__rhs.__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
     } else {
-      __union_.__unex_ = __rhs.__union_.__unex_;
+      __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
     }
     // note: only reached if no exception+rollback was done inside __reinit_expected
-    __has_val_ = __rhs.__has_val_;
+    __repr_.__has_val_ = __rhs.__repr_.__has_val_;
     return *this;
   }
 
@@ -353,17 +334,17 @@ class expected {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__has_val_ && __rhs.__has_val_) {
-      __union_.__val_ = std::move(__rhs.__union_.__val_);
-    } else if (__has_val_) {
-      __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__rhs.__union_.__unex_));
-    } else if (__rhs.__has_val_) {
-      __reinit_expected(__union_.__val_, __union_.__unex_, std::move(__rhs.__union_.__val_));
+    if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
+      __repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
+    } else if (__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
+    } else if (__rhs.__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
     } else {
-      __union_.__unex_ = std::move(__rhs.__union_.__unex_);
+      __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
     }
     // note: only reached if no exception+rollback was done inside __reinit_expected
-    __has_val_ = __rhs.__has_val_;
+    __repr_.__has_val_ = __rhs.__repr_.__has_val_;
     return *this;
   }
 
@@ -377,11 +358,11 @@ class expected {
               is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__has_val_) {
-      __union_.__val_ = std::forward<_Up>(__v);
+    if (__repr_.__has_val_) {
+      __repr_.__union_.__val_ = std::forward<_Up>(__v);
     } else {
-      __reinit_expected(__union_.__val_, __union_.__unex_, std::forward<_Up>(__v));
-      __has_val_ = true;
+      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, std::forward<_Up>(__v));
+      __repr_.__has_val_ = true;
     }
     return *this;
   }
@@ -400,11 +381,11 @@ class expected {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (__has_val_) {
-      __reinit_expected(__union_.__unex_, __union_.__val_, __un.error());
-      __has_val_ = false;
+    if (__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, __un.error());
+      __repr_.__has_val_ = false;
     } else {
-      __union_.__unex_ = __un.error();
+      __repr_.__union_.__unex_ = __un.error();
     }
     return *this;
   }
@@ -412,11 +393,11 @@ class expected {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (__has_val_) {
-      __reinit_expected(__union_.__unex_, __union_.__val_, std::move(__un.error()));
-      __has_val_ = false;
+    if (__repr_.__has_val_) {
+      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, std::move(__un.error()));
+      __repr_.__has_val_ = false;
     } else {
-      __union_.__unex_ = std::move(__un.error());
+      __repr_.__union_.__unex_ = std::move(__un.error());
     }
     return *this;
   }
@@ -424,27 +405,27 @@ class expected {
   template <class... _Args>
     requires is_nothrow_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
-    if (__has_val_) {
-      std::destroy_at(std::addressof(__union_.__val_));
+    if (__repr_.__has_val_) {
+      std::destroy_at(std::addressof(__repr_.__union_.__val_));
     } else {
-      std::destroy_at(std::addressof(__union_.__unex_));
+      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
     }
-    std::construct_at(std::addressof(__union_.__val_), std::forward<_Args>(__args)...);
-    __has_val_ = true;
-    return __union_.__val_;
+    std::construct_at(std::addressof(__repr_.__union_.__val_), std::forward<_Args>(__args)...);
+    __repr_.__has_val_ = true;
+    return __repr_.__union_.__val_;
   }
 
   template <class _Up, class... _Args>
     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
-    if (__has_val_) {
-      std::destroy_at(std::addressof(__union_.__val_));
+    if (__repr_.__has_val_) {
+      std::destroy_at(std::addressof(__repr_.__union_.__val_));
     } else {
-      std::destroy_at(std::addressof(__union_.__unex_));
+      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
     }
-    std::construct_at(std::addressof(__union_.__val_), __il, std::forward<_Args>(__args)...);
-    __has_val_ = true;
-    return __union_.__val_;
+    std::construct_at(std::addressof(__repr_.__union_.__val_), __il, std::forward<_Args>(__args)...);
+    __repr_.__has_val_ = true;
+    return __repr_.__union_.__val_;
   }
 
 
@@ -464,46 +445,46 @@ class expected {
   {
     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
       if constexpr (is_nothrow_move_constructible_v<_Err>) {
-        _Err __tmp(std::move(__with_err.__union_.__unex_));
-        std::destroy_at(std::addressof(__with_err.__union_.__unex_));
+        _Err __tmp(std::move(__with_err.__repr_.__union_.__unex_));
+        std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(std::addressof(__with_err.__union_.__unex_), std::move(__tmp));
+          std::construct_at(std::addressof(__with_err.__repr_.__union_.__unex_), std::move(__tmp));
         });
-        std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__with_val.__union_.__val_));
+        std::construct_at(std::addressof(__with_err.__repr_.__union_.__val_), std::move(__with_val.__repr_.__union_.__val_));
         __trans.__complete();
-        std::destroy_at(std::addressof(__with_val.__union_.__val_));
-        std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__tmp));
+        std::destroy_at(std::addressof(__with_val.__repr_.__union_.__val_));
+        std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__tmp));
       } else {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
-        _Tp __tmp(std::move(__with_val.__union_.__val_));
-        std::destroy_at(std::addressof(__with_val.__union_.__val_));
+        _Tp __tmp(std::move(__with_val.__repr_.__union_.__val_));
+        std::destroy_at(std::addressof(__with_val.__repr_.__union_.__val_));
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(std::addressof(__with_val.__union_.__val_), std::move(__tmp));
+          std::construct_at(std::addressof(__with_val.__repr_.__union_.__val_), std::move(__tmp));
         });
-        std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
+        std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__with_err.__repr_.__union_.__unex_));
         __trans.__complete();
-        std::destroy_at(std::addressof(__with_err.__union_.__unex_));
-        std::construct_at(std::addressof(__with_err.__union_.__val_), std::move(__tmp));
+        std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
+        std::construct_at(std::addressof(__with_err.__repr_.__union_.__val_), std::move(__tmp));
       }
-      __with_val.__has_val_ = false;
-      __with_err.__has_val_ = true;
+      __with_val.__repr_.__has_val_ = false;
+      __with_err.__repr_.__has_val_ = true;
     };
 
-    if (__has_val_) {
-      if (__rhs.__has_val_) {
+    if (__repr_.__has_val_) {
+      if (__rhs.__repr_.__has_val_) {
         using std::swap;
-        swap(__union_.__val_, __rhs.__union_.__val_);
+        swap(__repr_.__union_.__val_, __rhs.__repr_.__union_.__val_);
       } else {
         __swap_val_unex_impl(*this, __rhs);
       }
     } else {
-      if (__rhs.__has_val_) {
+      if (__rhs.__repr_.__has_val_) {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(__union_.__unex_, __rhs.__union_.__unex_);
+        swap(__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
       }
     }
   }
@@ -517,105 +498,105 @@ class expected {
 
   // [expected.object.obs], observers
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
-    return __union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return __repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
-    return __union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return __repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(__repr_.__union_.__val_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __repr_.__has_val_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __repr_.__has_val_; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!__has_val_) {
+    if (!__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return __union_.__val_;
+    return __repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!__has_val_) {
+    if (!__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return __union_.__val_;
+    return __repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!__has_val_) {
+    if (!__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(__union_.__val_);
+    return std::move(__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!__has_val_) {
+    if (!__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(__union_.__val_);
+    return std::move(__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return __union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return __repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return __union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return __repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(__repr_.__union_.__unex_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(__repr_.__union_.__unex_);
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return __has_val_ ? __union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
+    return __repr_.__has_val_ ? __repr_.__union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return __has_val_ ? std::move(__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
+    return __repr_.__has_val_ ? std::move(__repr_.__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up = _Err>
@@ -645,7 +626,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), __union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
     }
     return _Up(unexpect, error());
   }
@@ -658,7 +639,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), __union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
     }
     return _Up(unexpect, error());
   }
@@ -672,7 +653,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -686,7 +667,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -699,7 +680,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, __union_.__val_);
+      return _Gp(in_place, __repr_.__union_.__val_);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -712,7 +693,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, __union_.__val_);
+      return _Gp(in_place, __repr_.__union_.__val_);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -726,7 +707,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(__union_.__val_));
+      return _Gp(in_place, std::move(__repr_.__union_.__val_));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -740,7 +721,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(__union_.__val_));
+      return _Gp(in_place, std::move(__repr_.__union_.__val_));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -753,9 +734,9 @@ class expected {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __repr_.__union_.__val_);
     } else {
-      std::invoke(std::forward<_Func>(__f), __union_.__val_);
+      std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
       return expected<_Up, _Err>();
     }
   }
@@ -768,9 +749,9 @@ class expected {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __repr_.__union_.__val_);
     } else {
-      std::invoke(std::forward<_Func>(__f), __union_.__val_);
+      std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
       return expected<_Up, _Err>();
     }
   }
@@ -784,9 +765,9 @@ class expected {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_));
+          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
       return expected<_Up, _Err>();
     }
   }
@@ -800,9 +781,9 @@ class expected {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__union_.__val_));
+          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
       return expected<_Up, _Err>();
     }
   }
@@ -814,7 +795,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, __union_.__val_);
+      return expected<_Tp, _Gp>(in_place, __repr_.__union_.__val_);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -826,7 +807,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, __union_.__val_);
+      return expected<_Tp, _Gp>(in_place, __repr_.__union_.__val_);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -838,7 +819,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(__repr_.__union_.__val_));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -851,7 +832,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(__repr_.__union_.__val_));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -861,25 +842,25 @@ class expected {
   template <class _T2, class _E2>
     requires(!is_void_v<_T2>)
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
-    if (__x.__has_val_ != __y.__has_val_) {
+    if (__x.__repr_.__has_val_ != __y.__repr_.__has_val_) {
       return false;
     } else {
-      if (__x.__has_val_) {
-        return __x.__union_.__val_ == __y.__union_.__val_;
+      if (__x.__repr_.__has_val_) {
+        return __x.__repr_.__union_.__val_ == __y.__repr_.__union_.__val_;
       } else {
-        return __x.__union_.__unex_ == __y.__union_.__unex_;
+        return __x.__repr_.__union_.__unex_ == __y.__repr_.__union_.__unex_;
       }
     }
   }
 
   template <class _T2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
-    return __x.__has_val_ && static_cast<bool>(__x.__union_.__val_ == __v);
+    return __x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__val_ == __v);
   }
 
   template <class _E2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
-    return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __e.error());
+    return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __e.error());
   }
 
 private:
@@ -971,9 +952,7 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_padding_t<__union_t<_Tp, _Err>> __padding_{};
+  __expected_repr<__union_t<_Tp, _Err>> __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -1004,7 +983,7 @@ class expected<_Tp, _Err> {
   using rebind = expected<_Up, error_type>;
 
   // [expected.void.ctor], constructors
-  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __has_val_(true) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_{.__union_{}, .__has_val_ = true} {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -1015,7 +994,7 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
     noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
-      : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
+      : __repr_{.__union_{__rhs.__repr_.__has_val_, __rhs.__repr_.__union_}, .__has_val_ = __rhs.__repr_.__has_val_} {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
@@ -1024,61 +1003,61 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
     noexcept(is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
-      : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
+      : __repr_{.__union_{__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)}, .__has_val_ = __rhs.__repr_.__has_val_} {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const expected<_Up, _OtherErr>& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __union_(__rhs.__has_val_, __rhs.__union_), __has_val_(__rhs.__has_val_) {}
+      : __repr_{.__union_{__rhs.__repr_.__has_val_, __rhs.__repr_.__union_}, .__has_val_ = __rhs.__repr_.__has_val_} {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __union_(__rhs.__has_val_, std::move(__rhs.__union_)), __has_val_(__rhs.__has_val_) {}
+      : __repr_{.__union_{__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)}, .__has_val_ = __rhs.__repr_.__has_val_} {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __union_(std::unexpect, __unex.error()), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, __unex.error()}, .__has_val_ = false} {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __union_(std::unexpect, std::move(__unex.error())), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, std::move(__unex.error())}, .__has_val_ = false} {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __has_val_(true) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_{.__union_{}, .__has_val_ = true} {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __union_(std::unexpect, std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __union_(std::unexpect, __il, std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{std::unexpect, __il, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
 private:
   template <class _Func>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f)
-      : __has_val_(true) {
+      : __repr_{.__union_{}, .__has_val_ = true} {
     std::invoke(std::forward<_Func>(__f));
   }
 
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __union_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...), __has_val_(false) {}
+      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = false} {}
 
 public:
   // [expected.void.dtor], destructor
@@ -1090,8 +1069,8 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
     requires(!is_trivially_destructible_v<_Err>)
   {
-    if (!__has_val_) {
-      std::destroy_at(std::addressof(__union_.__unex_));
+    if (!__repr_.__has_val_) {
+      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
     }
   }
 
@@ -1103,17 +1082,17 @@ class expected<_Tp, _Err> {
     noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
   {
-    if (__has_val_) {
-      if (!__rhs.__has_val_) {
-        std::construct_at(std::addressof(__union_.__unex_), __rhs.__union_.__unex_);
-        __has_val_ = false;
+    if (__repr_.__has_val_) {
+      if (!__rhs.__repr_.__has_val_) {
+        std::construct_at(std::addressof(__repr_.__union_.__unex_), __rhs.__repr_.__union_.__unex_);
+        __repr_.__has_val_ = false;
       }
     } else {
-      if (__rhs.__has_val_) {
-        std::destroy_at(std::addressof(__union_.__unex_));
-        __has_val_ = true;
+      if (__rhs.__repr_.__has_val_) {
+        std::destroy_at(std::addressof(__repr_.__union_.__unex_));
+        __repr_.__has_val_ = true;
       } else {
-        __union_.__unex_ = __rhs.__union_.__unex_;
+        __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
       }
     }
     return *this;
@@ -1127,17 +1106,17 @@ class expected<_Tp, _Err> {
     requires(is_move_assignable_v<_Err> &&
              is_move_constructible_v<_Err>)
   {
-    if (__has_val_) {
-      if (!__rhs.__has_val_) {
-        std::construct_at(std::addressof(__union_.__unex_), std::move(__rhs.__union_.__unex_));
-        __has_val_ = false;
+    if (__repr_.__has_val_) {
+      if (!__rhs.__repr_.__has_val_) {
+        std::construct_at(std::addressof(__repr_.__union_.__unex_), std::move(__rhs.__repr_.__union_.__unex_));
+        __repr_.__has_val_ = false;
       }
     } else {
-      if (__rhs.__has_val_) {
-        std::destroy_at(std::addressof(__union_.__unex_));
-        __has_val_ = true;
+      if (__rhs.__repr_.__has_val_) {
+        std::destroy_at(std::addressof(__repr_.__union_.__unex_));
+        __repr_.__has_val_ = true;
       } else {
-        __union_.__unex_ = std::move(__rhs.__union_.__unex_);
+        __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
       }
     }
     return *this;
@@ -1146,11 +1125,11 @@ class expected<_Tp, _Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (__has_val_) {
-      std::construct_at(std::addressof(__union_.__unex_), __un.error());
-      __has_val_ = false;
+    if (__repr_.__has_val_) {
+      std::construct_at(std::addressof(__repr_.__union_.__unex_), __un.error());
+      __repr_.__has_val_ = false;
     } else {
-      __union_.__unex_ = __un.error();
+      __repr_.__union_.__unex_ = __un.error();
     }
     return *this;
   }
@@ -1158,19 +1137,19 @@ class expected<_Tp, _Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (__has_val_) {
-      std::construct_at(std::addressof(__union_.__unex_), std::move(__un.error()));
-      __has_val_ = false;
+    if (__repr_.__has_val_) {
+      std::construct_at(std::addressof(__repr_.__union_.__unex_), std::move(__un.error()));
+      __repr_.__has_val_ = false;
     } else {
-      __union_.__unex_ = std::move(__un.error());
+      __repr_.__union_.__unex_ = std::move(__un.error());
     }
     return *this;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
-    if (!__has_val_) {
-      std::destroy_at(std::addressof(__union_.__unex_));
-      __has_val_ = true;
+    if (!__repr_.__has_val_) {
+      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
+      __repr_.__has_val_ = true;
     }
   }
 
@@ -1180,22 +1159,22 @@ class expected<_Tp, _Err> {
     requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>)
   {
     auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
-      std::construct_at(std::addressof(__with_val.__union_.__unex_), std::move(__with_err.__union_.__unex_));
-      std::destroy_at(std::addressof(__with_err.__union_.__unex_));
-      __with_val.__has_val_ = false;
-      __with_err.__has_val_ = true;
+      std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__with_err.__repr_.__union_.__unex_));
+      std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
+      __with_val.__repr_.__has_val_ = false;
+      __with_err.__repr_.__has_val_ = true;
     };
 
-    if (__has_val_) {
-      if (!__rhs.__has_val_) {
+    if (__repr_.__has_val_) {
+      if (!__rhs.__repr_.__has_val_) {
         __swap_val_unex_impl(*this, __rhs);
       }
     } else {
-      if (__rhs.__has_val_) {
+      if (__rhs.__repr_.__has_val_) {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(__union_.__unex_, __rhs.__union_.__unex_);
+        swap(__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
       }
     }
   }
@@ -1208,44 +1187,44 @@ class expected<_Tp, _Err> {
   }
 
   // [expected.void.obs], observers
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __repr_.__has_val_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __repr_.__has_val_; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__has_val_, "expected::operator* requires the expected to contain a value");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
-    if (!__has_val_) {
-      std::__throw_bad_expected_access<_Err>(__union_.__unex_);
+    if (!__repr_.__has_val_) {
+      std::__throw_bad_expected_access<_Err>(__repr_.__union_.__unex_);
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
-    if (!__has_val_) {
-      std::__throw_bad_expected_access<_Err>(std::move(__union_.__unex_));
+    if (!__repr_.__has_val_) {
+      std::__throw_bad_expected_access<_Err>(std::move(__repr_.__union_.__unex_));
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return __union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return __repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return __union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return __repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(__repr_.__union_.__unex_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(__repr_.__union_.__unex_);
   }
 
   template <class _Up = _Err>
@@ -1481,16 +1460,16 @@ class expected<_Tp, _Err> {
   template <class _T2, class _E2>
     requires is_void_v<_T2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
-    if (__x.__has_val_ != __y.__has_val_) {
+    if (__x.__repr_.__has_val_ != __y.__repr_.__has_val_) {
       return false;
     } else {
-      return __x.__has_val_ || static_cast<bool>(__x.__union_.__unex_ == __y.__union_.__unex_);
+      return __x.__repr_.__has_val_ || static_cast<bool>(__x.__repr_.__union_.__unex_ == __y.__repr_.__union_.__unex_);
     }
   }
 
   template <class _E2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
-    return !__x.__has_val_ && static_cast<bool>(__x.__union_.__unex_ == __y.error());
+    return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __y.error());
   }
 
 private:
@@ -1569,9 +1548,7 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_padding_t<__union_t<_Err>> __padding_{};
+  __expected_repr<__union_t<_Err>> __repr_;
 };
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index 06f597d54871ee1..80209db9045b506 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -13,6 +13,7 @@
 // test [[no_unique_address]] is applied to the union
 
 #include <expected>
+#include <memory>
 
 struct Empty {};
 
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index 29cf8dff0d2b288..db2e4259eb8c797 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -13,6 +13,7 @@
 // test [[no_unique_address]] is applied to the union
 
 #include <expected>
+#include <memory>
 
 struct Empty {};
 

>From 7d1ba8b8bfb988106d0830cf5ad092f865952e20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 10:52:00 +0200
Subject: [PATCH 06/31] transparently replace whole 'repr' struct on mutating
 operations

---
 libcxx/include/__expected/expected.h          | 208 ++++++++++--------
 .../no_unique_address.compile.pass.cpp        |   3 +-
 .../no_unique_address.compile.pass.cpp        |   3 +-
 3 files changed, 125 insertions(+), 89 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index ab7cae1c1007f24..cd5e2d64411b9ca 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -89,12 +89,6 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-template <class _Union>
-struct __expected_repr {
-    [[no_unique_address]] _Union __union_;
-    [[no_unique_address]] bool __has_val_;
-};
-
 template <class _Tp, class _Err>
 class expected {
   static_assert(
@@ -126,7 +120,7 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr expected()
     noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
     requires is_default_constructible_v<_Tp>
-      : __repr_{.__union_{std::in_place}, .__has_val_ = true} {}
+      : __repr_(std::in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -141,7 +135,7 @@ class expected {
     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
-      : __repr_{.__union_{__other.__repr_.__has_val_, __other.__repr_.__union_}, .__has_val_ = __other.__repr_.__has_val_} { }
+      : __repr_(__other.__repr_.__has_val_, __other.__repr_.__union_) { }
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
@@ -152,8 +146,7 @@ class expected {
     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
-      : __repr_{.__union_{__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)},
-                .__has_val_ = __other.__repr_.__has_val_} { }
+      : __repr_(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) { }
 
 private:
   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
@@ -178,12 +171,12 @@ class expected {
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = true} {}
+      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
 public:
   template <class _Up, class _OtherErr>
@@ -193,16 +186,14 @@ class expected {
   expected(const expected<_Up, _OtherErr>& __other)
     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_{.__union_{__other.__repr_.__has_val_, __other.__repr_.__union_},
-                .__has_val_ = __other.__repr_.__has_val_} {}
+      : __repr_(__other.__repr_.__has_val_, __other.__repr_.__union_) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __other)
     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_{.__union_{__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)},
-                .__has_val_ = __other.__repr_.__has_val_} {}
+      : __repr_(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) {}
 
   template <class _Up = _Tp>
     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
@@ -210,84 +201,72 @@ class expected {
              (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
       expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
-      : __repr_{.__union_{std::in_place, std::forward<_Up>(__u)}, .__has_val_ = true} {}
+      : __repr_(std::in_place, std::forward<_Up>(__u)) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_{.__union_{std::unexpect, __unex.error()}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_{.__union_{std::unexpect, std::move(__unex.error())}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, std::move(__unex.error())) {}
 
   template <class... _Args>
     requires is_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
-      : __repr_{.__union_{std::in_place, std::forward<_Args>(__args)...}, .__has_val_ = true} {}
+      : __repr_(std::in_place, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_{.__union_{std::in_place, __il, std::forward<_Args>(__args)...}, .__has_val_ = true} {}
+      : __repr_(std::in_place, __il, std::forward<_Args>(__args)...) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_{.__union_{std::unexpect, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_{.__union_{std::unexpect, __il, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, __il, std::forward<_Args>(__args)...) {}
 
   // [expected.object.dtor], destructor
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
-    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
-    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
-  {
-    if (__repr_.__has_val_) {
-      std::destroy_at(std::addressof(__repr_.__union_.__val_));
-    } else {
-      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-    }
-  }
+  _LIBCPP_HIDE_FROM_ABI constexpr ~expected() = default;
 
 private:
-  template <class _T1, class _T2, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI static constexpr void __reinit_expected(_T1& __newval, _T2& __oldval, _Args&&... __args) {
+  template <class _Tag, class _OtherTag, class _T1, class _T2, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(_T2& __oldval, _Args&&... __args) {
     if constexpr (is_nothrow_constructible_v<_T1, _Args...>) {
-      std::destroy_at(std::addressof(__oldval));
-      std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
+      std::destroy_at(&__repr_);
+      std::construct_at(&__repr_, _Tag{}, std::forward<_Args>(__args)...);
     } else if constexpr (is_nothrow_move_constructible_v<_T1>) {
       _T1 __tmp(std::forward<_Args>(__args)...);
-      std::destroy_at(std::addressof(__oldval));
-      std::construct_at(std::addressof(__newval), std::move(__tmp));
+      std::destroy_at(&__repr_);
+      std::construct_at(&__repr_, _Tag{}, std::move(__tmp));
     } else {
       static_assert(
           is_nothrow_move_constructible_v<_T2>,
           "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
           "be reverted to the previous state in case an exception is thrown during the assignment.");
       _T2 __tmp(std::move(__oldval));
-      std::destroy_at(std::addressof(__oldval));
+      std::destroy_at(&__repr_);
       auto __trans =
-          std::__make_exception_guard([&] { std::construct_at(std::addressof(__oldval), std::move(__tmp)); });
-      std::construct_at(std::addressof(__newval), std::forward<_Args>(__args)...);
+          std::__make_exception_guard([&] { std::construct_at(&__repr_, _OtherTag{}, std::move(__tmp)); });
+      std::construct_at(&__repr_, _Tag{}, std::forward<_Args>(__args)...);
       __trans.__complete();
     }
   }
@@ -311,14 +290,14 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
     } else if (__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
+      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+          __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
+      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+          __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
     } else {
       __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
     }
-    // note: only reached if no exception+rollback was done inside __reinit_expected
-    __repr_.__has_val_ = __rhs.__repr_.__has_val_;
     return *this;
   }
 
@@ -337,14 +316,14 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
     } else if (__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
+      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+          __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
+      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+          __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
     } else {
       __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
     }
-    // note: only reached if no exception+rollback was done inside __reinit_expected
-    __repr_.__has_val_ = __rhs.__repr_.__has_val_;
     return *this;
   }
 
@@ -361,8 +340,8 @@ class expected {
     if (__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::forward<_Up>(__v);
     } else {
-      __reinit_expected(__repr_.__union_.__val_, __repr_.__union_.__unex_, std::forward<_Up>(__v));
-      __repr_.__has_val_ = true;
+      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+          __repr_.__union_.__unex_, std::forward<_Up>(__v));
     }
     return *this;
   }
@@ -382,8 +361,8 @@ class expected {
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, __un.error());
-      __repr_.__has_val_ = false;
+      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+          __repr_.__union_.__val_, __un.error());
     } else {
       __repr_.__union_.__unex_ = __un.error();
     }
@@ -394,8 +373,8 @@ class expected {
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected(__repr_.__union_.__unex_, __repr_.__union_.__val_, std::move(__un.error()));
-      __repr_.__has_val_ = false;
+      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+          __repr_.__union_.__val_, std::move(__un.error()));
     } else {
       __repr_.__union_.__unex_ = std::move(__un.error());
     }
@@ -405,26 +384,16 @@ class expected {
   template <class... _Args>
     requires is_nothrow_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
-    if (__repr_.__has_val_) {
-      std::destroy_at(std::addressof(__repr_.__union_.__val_));
-    } else {
-      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-    }
-    std::construct_at(std::addressof(__repr_.__union_.__val_), std::forward<_Args>(__args)...);
-    __repr_.__has_val_ = true;
+    std::destroy_at(&__repr_);
+    std::construct_at(&__repr_, std::in_place, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
   template <class _Up, class... _Args>
     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
-    if (__repr_.__has_val_) {
-      std::destroy_at(std::addressof(__repr_.__union_.__val_));
-    } else {
-      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-    }
-    std::construct_at(std::addressof(__repr_.__union_.__val_), __il, std::forward<_Args>(__args)...);
-    __repr_.__has_val_ = true;
+    std::destroy_at(&__repr_);
+    std::construct_at(&__repr_, std::in_place, __il, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
@@ -443,33 +412,31 @@ class expected {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
+    auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       if constexpr (is_nothrow_move_constructible_v<_Err>) {
         _Err __tmp(std::move(__with_err.__repr_.__union_.__unex_));
-        std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
+        std::destroy_at(&__with_err.__repr_);
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(std::addressof(__with_err.__repr_.__union_.__unex_), std::move(__tmp));
+          std::construct_at(&__with_err.__repr_, std::unexpect, std::move(__tmp));
         });
-        std::construct_at(std::addressof(__with_err.__repr_.__union_.__val_), std::move(__with_val.__repr_.__union_.__val_));
+        std::construct_at(&__with_err.__repr_, std::in_place, std::move(__with_val.__repr_.__union_.__val_));
         __trans.__complete();
-        std::destroy_at(std::addressof(__with_val.__repr_.__union_.__val_));
-        std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__tmp));
+        std::destroy_at(&__with_val.__repr_);
+        std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__tmp));
       } else {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
         _Tp __tmp(std::move(__with_val.__repr_.__union_.__val_));
-        std::destroy_at(std::addressof(__with_val.__repr_.__union_.__val_));
+        std::destroy_at(&__with_val.__repr_);
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(std::addressof(__with_val.__repr_.__union_.__val_), std::move(__tmp));
+          std::construct_at(&__with_val.__repr_, std::in_place, std::move(__tmp));
         });
-        std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__with_err.__repr_.__union_.__unex_));
+        std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
         __trans.__complete();
-        std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
-        std::construct_at(std::addressof(__with_err.__repr_.__union_.__val_), std::move(__tmp));
+        std::destroy_at(&__with_err.__repr_);
+        std::construct_at(&__with_err.__repr_, std::in_place, std::move(__tmp));
       }
-      __with_val.__repr_.__has_val_ = false;
-      __with_err.__repr_.__has_val_ = true;
     };
 
     if (__repr_.__has_val_) {
@@ -952,7 +919,74 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  __expected_repr<__union_t<_Tp, _Err>> __repr_;
+  struct __expected_repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::in_place_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::unexpect_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+        std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _Args&&... __args)
+        : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+      requires(is_copy_constructible_v<_Tp> &&
+               is_copy_constructible_v<_Err> &&
+               is_trivially_copy_constructible_v<_Tp> &&
+               is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+      requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
+                && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+      requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+      requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+    {
+      if (__has_val_) {
+        std::destroy_at(std::addressof(__union_.__val_));
+      } else {
+        std::destroy_at(std::addressof(__union_.__unex_));
+      }
+    }
+
+  private:
+    template <class _Up, class _OtherErr> friend class expected;
+
+    [[no_unique_address]] __union_t<_Tp, _Err> __union_;
+    [[no_unique_address]] bool __has_val_;
+  };
+
+  __expected_repr __repr_;
+};
+
+template <class _Union>
+struct __expected_repr {
+  [[no_unique_address]] _Union __union_;
+  [[no_unique_address]] bool __has_val_;
 };
 
 template <class _Tp, class _Err>
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index 80209db9045b506..8eeec70ff0e4243 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -50,4 +50,5 @@ static_assert(sizeof(std::expected<Empty, BoolWithPadding>) ==
 
 // In this case, there should be tail padding in the `expected` because `A`
 // itself does _not_ have tail padding.
-static_assert(sizeof(std::expected<A, A>) > std::__libcpp_datasizeof<std::expected<A, A>>::value);
+// XXX
+// static_assert(sizeof(std::expected<A, A>) > std::__libcpp_datasizeof<std::expected<A, A>>::value);
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index db2e4259eb8c797..2129aa7b2405c7e 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -44,4 +44,5 @@ static_assert(sizeof(std::expected<void, BoolWithPadding>) ==
 
 // In this case, there should be tail padding in the `expected` because `A`
 // itself does _not_ have tail padding.
-static_assert(sizeof(std::expected<void, A>) > std::__libcpp_datasizeof<std::expected<void, A>>::value);
+// XXX
+// static_assert(sizeof(std::expected<void, A>) > std::__libcpp_datasizeof<std::expected<void, A>>::value);

>From 19c88ebdbab817970d111ec46570ebff254d9912 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 11:39:31 +0200
Subject: [PATCH 07/31] do the same for 'expected<void>'

---
 libcxx/include/__expected/expected.h | 150 +++++++++++++++++----------
 1 file changed, 97 insertions(+), 53 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index cd5e2d64411b9ca..f15500d79806f1a 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -863,7 +863,7 @@ class expected {
       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the expected's destructor handles this
+    // the __expected_repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
 
     _ValueType __val_;
@@ -910,7 +910,7 @@ class expected {
       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the expected's destructor handles this
+    // the __expected_repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
     {}
@@ -974,7 +974,8 @@ class expected {
     }
 
   private:
-    template <class _Up, class _OtherErr> friend class expected;
+    template <class, class>
+    friend class expected;
 
     [[no_unique_address]] __union_t<_Tp, _Err> __union_;
     [[no_unique_address]] bool __has_val_;
@@ -983,12 +984,6 @@ class expected {
   __expected_repr __repr_;
 };
 
-template <class _Union>
-struct __expected_repr {
-  [[no_unique_address]] _Union __union_;
-  [[no_unique_address]] bool __has_val_;
-};
-
 template <class _Tp, class _Err>
   requires is_void_v<_Tp>
 class expected<_Tp, _Err> {
@@ -1017,7 +1012,7 @@ class expected<_Tp, _Err> {
   using rebind = expected<_Up, error_type>;
 
   // [expected.void.ctor], constructors
-  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_{.__union_{}, .__has_val_ = true} {}
+  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_(std::in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -1028,7 +1023,7 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
     noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
-      : __repr_{.__union_{__rhs.__repr_.__has_val_, __rhs.__repr_.__union_}, .__has_val_ = __rhs.__repr_.__has_val_} {}
+      : __repr_(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
@@ -1037,79 +1032,86 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
     noexcept(is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
-      : __repr_{.__union_{__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)}, .__has_val_ = __rhs.__repr_.__has_val_} {}
+      : __repr_(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const expected<_Up, _OtherErr>& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_{.__union_{__rhs.__repr_.__has_val_, __rhs.__repr_.__union_}, .__has_val_ = __rhs.__repr_.__has_val_} {}
+      : __repr_(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_{.__union_{__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)}, .__has_val_ = __rhs.__repr_.__has_val_} {}
+      : __repr_(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_{.__union_{std::unexpect, __unex.error()}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_{.__union_{std::unexpect, std::move(__unex.error())}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, std::move(__unex.error())) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_{.__union_{}, .__has_val_ = true} {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_(std::in_place) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_{.__union_{std::unexpect, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_{.__union_{std::unexpect, __il, std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(std::unexpect, __il, std::forward<_Args>(__args)...) {}
 
 private:
   template <class _Func>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f)
-      : __repr_{.__union_{}, .__has_val_ = true} {
+      : __repr_(std::in_place) {
     std::invoke(std::forward<_Func>(__f));
   }
 
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_{.__union_{__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...}, .__has_val_ = false} {}
+      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
 public:
   // [expected.void.dtor], destructor
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
-    requires is_trivially_destructible_v<_Err>
-  = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr ~expected() = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~expected()
-    requires(!is_trivially_destructible_v<_Err>)
-  {
-    if (!__repr_.__has_val_) {
-      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-    }
+private:
+  // precondition: has_value()
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(std::unexpect_t, _Args&&... __args) {
+    std::destroy_at(&__repr_);
+    auto __trans =
+        std::__make_exception_guard([&] { std::construct_at(&__repr_, std::in_place); });
+    std::construct_at(&__repr_, std::unexpect, std::forward<_Args>(__args)...);
+    __trans.__complete();
   }
 
-  // [expected.void.assign], assignment
+  // precondition: !has_value()
+  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(std::in_place_t) {
+    std::destroy_at(&__repr_);
+    std::construct_at(&__repr_, std::in_place);
+  }
 
+public:
+  // [expected.void.assign], assignment
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected&) = delete;
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const expected& __rhs)
@@ -1118,13 +1120,11 @@ class expected<_Tp, _Err> {
   {
     if (__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
-        std::construct_at(std::addressof(__repr_.__union_.__unex_), __rhs.__repr_.__union_.__unex_);
-        __repr_.__has_val_ = false;
+        __reinit_expected(std::unexpect, __rhs.__repr_.__union_.__unex_);
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
-        std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-        __repr_.__has_val_ = true;
+        __reinit_expected(std::in_place);
       } else {
         __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
       }
@@ -1142,13 +1142,11 @@ class expected<_Tp, _Err> {
   {
     if (__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
-        std::construct_at(std::addressof(__repr_.__union_.__unex_), std::move(__rhs.__repr_.__union_.__unex_));
-        __repr_.__has_val_ = false;
+        __reinit_expected(std::unexpect, std::move(__rhs.__repr_.__union_.__unex_));
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
-        std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-        __repr_.__has_val_ = true;
+        __reinit_expected(std::in_place);
       } else {
         __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
       }
@@ -1160,8 +1158,7 @@ class expected<_Tp, _Err> {
     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
     if (__repr_.__has_val_) {
-      std::construct_at(std::addressof(__repr_.__union_.__unex_), __un.error());
-      __repr_.__has_val_ = false;
+      __reinit_expected(std::unexpect, __un.error());
     } else {
       __repr_.__union_.__unex_ = __un.error();
     }
@@ -1172,8 +1169,7 @@ class expected<_Tp, _Err> {
     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
     if (__repr_.__has_val_) {
-      std::construct_at(std::addressof(__repr_.__union_.__unex_), std::move(__un.error()));
-      __repr_.__has_val_ = false;
+      __reinit_expected(std::unexpect, std::move(__un.error()));
     } else {
       __repr_.__union_.__unex_ = std::move(__un.error());
     }
@@ -1182,8 +1178,7 @@ class expected<_Tp, _Err> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
     if (!__repr_.__has_val_) {
-      std::destroy_at(std::addressof(__repr_.__union_.__unex_));
-      __repr_.__has_val_ = true;
+      __reinit_expected(std::in_place);
     }
   }
 
@@ -1192,11 +1187,11 @@ class expected<_Tp, _Err> {
     noexcept(is_nothrow_move_constructible_v<_Err> && is_nothrow_swappable_v<_Err>)
     requires(is_swappable_v<_Err> && is_move_constructible_v<_Err>)
   {
-    auto __swap_val_unex_impl = [&](expected& __with_val, expected& __with_err) {
-      std::construct_at(std::addressof(__with_val.__repr_.__union_.__unex_), std::move(__with_err.__repr_.__union_.__unex_));
-      std::destroy_at(std::addressof(__with_err.__repr_.__union_.__unex_));
-      __with_val.__repr_.__has_val_ = false;
-      __with_err.__repr_.__has_val_ = true;
+    auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
+      // May throw, but will re-engage `__with_val` in that case.
+      __with_val.__reinit_expected(std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+      // Will not throw.
+      __with_err.__reinit_expected(std::in_place);
     };
 
     if (__repr_.__has_val_) {
@@ -1534,7 +1529,7 @@ class expected<_Tp, _Err> {
       requires(is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the expected's destructor handles this
+    // the __expected_repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
 
     __empty_t __empty_;
@@ -1573,7 +1568,7 @@ class expected<_Tp, _Err> {
       requires(is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the expected's destructor handles this
+    // the __expected_repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(!is_trivially_destructible_v<_ErrorType>)
     {}
@@ -1582,7 +1577,56 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  __expected_repr<__union_t<_Err>> __repr_;
+  struct __expected_repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::in_place_t) : __union_(), __has_val_(true) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::unexpect_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _Args&&... __args)
+        : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+      requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+      requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+      requires(is_trivially_destructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+      requires(!is_trivially_destructible_v<_Err>)
+    {
+      if (!__has_val_) {
+        std::destroy_at(std::addressof(__union_.__unex_));
+      }
+    }
+
+  private:
+    template <class, class>
+    friend class expected;
+
+    [[no_unique_address]] __union_t<_Err> __union_;
+    [[no_unique_address]] bool __has_val_;
+  };
+
+  __expected_repr __repr_;
 };
 
 _LIBCPP_END_NAMESPACE_STD

>From 2002178b105b3a9e1a10ec91f7b6e9a4ad5b6aac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 11:40:48 +0200
Subject: [PATCH 08/31] remove unused 'expected<void>' constructor

---
 libcxx/include/__expected/expected.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index f15500d79806f1a..3f06915356ef90a 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -1077,12 +1077,6 @@ class expected<_Tp, _Err> {
       : __repr_(std::unexpect, __il, std::forward<_Args>(__args)...) {}
 
 private:
-  template <class _Func>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(__expected_construct_in_place_from_invoke_tag, _Func&& __f)
-      : __repr_(std::in_place) {
-    std::invoke(std::forward<_Func>(__f));
-  }
-
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)

>From 8d54a5f0450d8957464353a2b642979e31bfb7e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 11:48:59 +0200
Subject: [PATCH 09/31] remove unused datasizeof include

---
 libcxx/include/__expected/expected.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 3f06915356ef90a..280041a64bf07c8 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -18,7 +18,6 @@
 #include <__memory/addressof.h>
 #include <__memory/construct_at.h>
 #include <__type_traits/conjunction.h>
-#include <__type_traits/datasizeof.h>
 #include <__type_traits/disjunction.h>
 #include <__type_traits/integral_constant.h>
 #include <__type_traits/is_assignable.h>

>From 0e3641d0437d59dd77d23796336ae45a8b428051 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:29:09 +0200
Subject: [PATCH 10/31] rename 'std::in_place_t' to 'in_place_t'

Co-authored-by: philnik777 <nikolasklauser at berlin.de>
---
 libcxx/include/__expected/expected.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 280041a64bf07c8..76f0cdd2c6b89e3 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -833,7 +833,7 @@ class expected {
   template <class _ValueType, class _ErrorType>
   union __union_t {
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
         : __val_(std::forward<_Args>(__args)...) {}
 
     template <class... _Args>

>From fc36e3f5491e94c001d7104239b12d22c0b5c999 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:32:27 +0200
Subject: [PATCH 11/31] std::in_place -> in_place

---
 libcxx/include/__expected/expected.h | 56 ++++++++++++++--------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 76f0cdd2c6b89e3..87283556c863db0 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -119,7 +119,7 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr expected()
     noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
     requires is_default_constructible_v<_Tp>
-      : __repr_(std::in_place) {}
+      : __repr_(in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -200,7 +200,7 @@ class expected {
              (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
       expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
-      : __repr_(std::in_place, std::forward<_Up>(__u)) {}
+      : __repr_(in_place, std::forward<_Up>(__u)) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
@@ -220,14 +220,14 @@ class expected {
     requires is_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
-      : __repr_(std::in_place, std::forward<_Args>(__args)...) {}
+      : __repr_(in_place, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(std::in_place, __il, std::forward<_Args>(__args)...) {}
+      : __repr_(in_place, __il, std::forward<_Args>(__args)...) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
@@ -289,10 +289,10 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
     } else if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
     } else {
       __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
@@ -315,10 +315,10 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
     } else if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
     } else {
       __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
@@ -339,7 +339,7 @@ class expected {
     if (__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::forward<_Up>(__v);
     } else {
-      __reinit_expected<std::in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, std::forward<_Up>(__v));
     }
     return *this;
@@ -360,7 +360,7 @@ class expected {
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, __un.error());
     } else {
       __repr_.__union_.__unex_ = __un.error();
@@ -372,7 +372,7 @@ class expected {
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, std::in_place_t, _Err, _Tp>(
+      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, std::move(__un.error()));
     } else {
       __repr_.__union_.__unex_ = std::move(__un.error());
@@ -384,7 +384,7 @@ class expected {
     requires is_nothrow_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
     std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, std::in_place, std::forward<_Args>(__args)...);
+    std::construct_at(&__repr_, in_place, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
@@ -392,7 +392,7 @@ class expected {
     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
     std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, std::in_place, __il, std::forward<_Args>(__args)...);
+    std::construct_at(&__repr_, in_place, __il, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
@@ -418,7 +418,7 @@ class expected {
         auto __trans = std::__make_exception_guard([&] {
           std::construct_at(&__with_err.__repr_, std::unexpect, std::move(__tmp));
         });
-        std::construct_at(&__with_err.__repr_, std::in_place, std::move(__with_val.__repr_.__union_.__val_));
+        std::construct_at(&__with_err.__repr_, in_place, std::move(__with_val.__repr_.__union_.__val_));
         __trans.__complete();
         std::destroy_at(&__with_val.__repr_);
         std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__tmp));
@@ -429,12 +429,12 @@ class expected {
         _Tp __tmp(std::move(__with_val.__repr_.__union_.__val_));
         std::destroy_at(&__with_val.__repr_);
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(&__with_val.__repr_, std::in_place, std::move(__tmp));
+          std::construct_at(&__with_val.__repr_, in_place, std::move(__tmp));
         });
         std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
         __trans.__complete();
         std::destroy_at(&__with_err.__repr_);
-        std::construct_at(&__with_err.__repr_, std::in_place, std::move(__tmp));
+        std::construct_at(&__with_err.__repr_, in_place, std::move(__tmp));
       }
     };
 
@@ -880,7 +880,7 @@ class expected {
     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::in_place_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
         : __val_(std::forward<_Args>(__args)...) {}
 
     template <class... _Args>
@@ -922,7 +922,7 @@ class expected {
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::in_place_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
 
     template <class... _Args>
@@ -1011,7 +1011,7 @@ class expected<_Tp, _Err> {
   using rebind = expected<_Up, error_type>;
 
   // [expected.void.ctor], constructors
-  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_(std::in_place) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_(in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -1061,7 +1061,7 @@ class expected<_Tp, _Err> {
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
       : __repr_(std::unexpect, std::move(__unex.error())) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_(std::in_place) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_(in_place) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
@@ -1092,15 +1092,15 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(std::unexpect_t, _Args&&... __args) {
     std::destroy_at(&__repr_);
     auto __trans =
-        std::__make_exception_guard([&] { std::construct_at(&__repr_, std::in_place); });
+        std::__make_exception_guard([&] { std::construct_at(&__repr_, in_place); });
     std::construct_at(&__repr_, std::unexpect, std::forward<_Args>(__args)...);
     __trans.__complete();
   }
 
   // precondition: !has_value()
-  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(std::in_place_t) {
+  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(in_place_t) {
     std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, std::in_place);
+    std::construct_at(&__repr_, in_place);
   }
 
 public:
@@ -1117,7 +1117,7 @@ class expected<_Tp, _Err> {
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
-        __reinit_expected(std::in_place);
+        __reinit_expected(in_place);
       } else {
         __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
       }
@@ -1139,7 +1139,7 @@ class expected<_Tp, _Err> {
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
-        __reinit_expected(std::in_place);
+        __reinit_expected(in_place);
       } else {
         __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
       }
@@ -1171,7 +1171,7 @@ class expected<_Tp, _Err> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
     if (!__repr_.__has_val_) {
-      __reinit_expected(std::in_place);
+      __reinit_expected(in_place);
     }
   }
 
@@ -1184,7 +1184,7 @@ class expected<_Tp, _Err> {
       // May throw, but will re-engage `__with_val` in that case.
       __with_val.__reinit_expected(std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
       // Will not throw.
-      __with_err.__reinit_expected(std::in_place);
+      __with_err.__reinit_expected(in_place);
     };
 
     if (__repr_.__has_val_) {
@@ -1573,7 +1573,7 @@ class expected<_Tp, _Err> {
   struct __expected_repr {
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::in_place_t) : __union_(), __has_val_(true) {}
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t) : __union_(), __has_val_(true) {}
 
     template <class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::unexpect_t __tag, _Args&&... __args)

>From 883a2ce2f3d59d672b356ef0302fdcbf3420636c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:33:55 +0200
Subject: [PATCH 12/31] std::unexpect -> unexpect

---
 libcxx/include/__expected/expected.h | 62 ++++++++++++++--------------
 1 file changed, 31 insertions(+), 31 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 87283556c863db0..65921d4d157c64c 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -207,14 +207,14 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(std::unexpect, __unex.error()) {}
+      : __repr_(unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(std::unexpect, std::move(__unex.error())) {}
+      : __repr_(unexpect, std::move(__unex.error())) {}
 
   template <class... _Args>
     requires is_constructible_v<_Tp, _Args...>
@@ -233,14 +233,14 @@ class expected {
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_(std::unexpect, std::forward<_Args>(__args)...) {}
+      : __repr_(unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(std::unexpect, __il, std::forward<_Args>(__args)...) {}
+      : __repr_(unexpect, __il, std::forward<_Args>(__args)...) {}
 
   // [expected.object.dtor], destructor
 
@@ -289,10 +289,10 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
     } else if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
     } else {
       __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
@@ -315,10 +315,10 @@ class expected {
     if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
     } else if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
     } else if (__rhs.__repr_.__has_val_) {
-      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
     } else {
       __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
@@ -339,7 +339,7 @@ class expected {
     if (__repr_.__has_val_) {
       __repr_.__union_.__val_ = std::forward<_Up>(__v);
     } else {
-      __reinit_expected<in_place_t, std::unexpect_t, _Tp, _Err>(
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
           __repr_.__union_.__unex_, std::forward<_Up>(__v));
     }
     return *this;
@@ -360,7 +360,7 @@ class expected {
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, __un.error());
     } else {
       __repr_.__union_.__unex_ = __un.error();
@@ -372,7 +372,7 @@ class expected {
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected<std::unexpect_t, in_place_t, _Err, _Tp>(
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
           __repr_.__union_.__val_, std::move(__un.error()));
     } else {
       __repr_.__union_.__unex_ = std::move(__un.error());
@@ -416,12 +416,12 @@ class expected {
         _Err __tmp(std::move(__with_err.__repr_.__union_.__unex_));
         std::destroy_at(&__with_err.__repr_);
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(&__with_err.__repr_, std::unexpect, std::move(__tmp));
+          std::construct_at(&__with_err.__repr_, unexpect, std::move(__tmp));
         });
         std::construct_at(&__with_err.__repr_, in_place, std::move(__with_val.__repr_.__union_.__val_));
         __trans.__complete();
         std::destroy_at(&__with_val.__repr_);
-        std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__tmp));
+        std::construct_at(&__with_val.__repr_, unexpect, std::move(__tmp));
       } else {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
@@ -431,7 +431,7 @@ class expected {
         auto __trans = std::__make_exception_guard([&] {
           std::construct_at(&__with_val.__repr_, in_place, std::move(__tmp));
         });
-        std::construct_at(&__with_val.__repr_, std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+        std::construct_at(&__with_val.__repr_, unexpect, std::move(__with_err.__repr_.__union_.__unex_));
         __trans.__complete();
         std::destroy_at(&__with_err.__repr_);
         std::construct_at(&__with_err.__repr_, in_place, std::move(__tmp));
@@ -837,7 +837,7 @@ class expected {
         : __val_(std::forward<_Args>(__args)...) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
         : __unex_(std::forward<_Args>(__args)...) {}
 
     template <class _Func, class... _Args>
@@ -884,7 +884,7 @@ class expected {
         : __val_(std::forward<_Args>(__args)...) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
         : __unex_(std::forward<_Args>(__args)...) {}
 
     template <class _Func, class... _Args>
@@ -926,7 +926,7 @@ class expected {
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::unexpect_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>
@@ -1052,14 +1052,14 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(std::unexpect, __unex.error()) {}
+      : __repr_(unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(std::unexpect, std::move(__unex.error())) {}
+      : __repr_(unexpect, std::move(__unex.error())) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_(in_place) {}
 
@@ -1067,13 +1067,13 @@ class expected<_Tp, _Err> {
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_(std::unexpect, std::forward<_Args>(__args)...) {}
+      : __repr_(unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(std::unexpect, __il, std::forward<_Args>(__args)...) {}
+      : __repr_(unexpect, __il, std::forward<_Args>(__args)...) {}
 
 private:
   template <class _Func, class... _Args>
@@ -1089,11 +1089,11 @@ class expected<_Tp, _Err> {
 private:
   // precondition: has_value()
   template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(std::unexpect_t, _Args&&... __args) {
+  _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(unexpect_t, _Args&&... __args) {
     std::destroy_at(&__repr_);
     auto __trans =
         std::__make_exception_guard([&] { std::construct_at(&__repr_, in_place); });
-    std::construct_at(&__repr_, std::unexpect, std::forward<_Args>(__args)...);
+    std::construct_at(&__repr_, unexpect, std::forward<_Args>(__args)...);
     __trans.__complete();
   }
 
@@ -1113,7 +1113,7 @@ class expected<_Tp, _Err> {
   {
     if (__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
-        __reinit_expected(std::unexpect, __rhs.__repr_.__union_.__unex_);
+        __reinit_expected(unexpect, __rhs.__repr_.__union_.__unex_);
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
@@ -1135,7 +1135,7 @@ class expected<_Tp, _Err> {
   {
     if (__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
-        __reinit_expected(std::unexpect, std::move(__rhs.__repr_.__union_.__unex_));
+        __reinit_expected(unexpect, std::move(__rhs.__repr_.__union_.__unex_));
       }
     } else {
       if (__rhs.__repr_.__has_val_) {
@@ -1151,7 +1151,7 @@ class expected<_Tp, _Err> {
     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected(std::unexpect, __un.error());
+      __reinit_expected(unexpect, __un.error());
     } else {
       __repr_.__union_.__unex_ = __un.error();
     }
@@ -1162,7 +1162,7 @@ class expected<_Tp, _Err> {
     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
     if (__repr_.__has_val_) {
-      __reinit_expected(std::unexpect, std::move(__un.error()));
+      __reinit_expected(unexpect, std::move(__un.error()));
     } else {
       __repr_.__union_.__unex_ = std::move(__un.error());
     }
@@ -1182,7 +1182,7 @@ class expected<_Tp, _Err> {
   {
     auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       // May throw, but will re-engage `__with_val` in that case.
-      __with_val.__reinit_expected(std::unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+      __with_val.__reinit_expected(unexpect, std::move(__with_err.__repr_.__union_.__unex_));
       // Will not throw.
       __with_err.__reinit_expected(in_place);
     };
@@ -1502,7 +1502,7 @@ class expected<_Tp, _Err> {
     _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
         : __unex_(std::forward<_Args>(__args)...) {}
 
     template <class _Func, class... _Args>
@@ -1541,7 +1541,7 @@ class expected<_Tp, _Err> {
     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(std::unexpect_t, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
         : __unex_(std::forward<_Args>(__args)...) {}
 
     template <class _Func, class... _Args>
@@ -1576,7 +1576,7 @@ class expected<_Tp, _Err> {
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t) : __union_(), __has_val_(true) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(std::unexpect_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>

>From f502580223cbe1375744b50af8365f0b104b2122 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:37:54 +0200
Subject: [PATCH 13/31] use _LIBCPP_NO_UNIQUE_ADDRESS

Co-authored-by: philnik777 <nikolasklauser at berlin.de>
---
 libcxx/include/__expected/expected.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 65921d4d157c64c..a579dc767560771 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -976,8 +976,8 @@ class expected {
     template <class, class>
     friend class expected;
 
-    [[no_unique_address]] __union_t<_Tp, _Err> __union_;
-    [[no_unique_address]] bool __has_val_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
   __expected_repr __repr_;

>From 98156c54fdb4190eb8bd86447545fff4ad9752af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:39:00 +0200
Subject: [PATCH 14/31] use _LIBCPP_NO_UNIQUE_ADDRESS

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

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index a579dc767560771..d8f0c97c5f9ff9f 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -1615,8 +1615,8 @@ class expected<_Tp, _Err> {
     template <class, class>
     friend class expected;
 
-    [[no_unique_address]] __union_t<_Err> __union_;
-    [[no_unique_address]] bool __has_val_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
   __expected_repr __repr_;

>From a7f2cb8bc7c017ba6064ce81913b996e056c59bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 13:43:23 +0200
Subject: [PATCH 15/31] remove _LIBCPP_GCC_DIAGNOSTIC_IGNORED (should be
 separate issue)

---
 libcxx/include/__type_traits/datasizeof.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libcxx/include/__type_traits/datasizeof.h b/libcxx/include/__type_traits/datasizeof.h
index 96404ad15a73376..5688e3293a69eb5 100644
--- a/libcxx/include/__type_traits/datasizeof.h
+++ b/libcxx/include/__type_traits/datasizeof.h
@@ -51,7 +51,6 @@ struct __libcpp_datasizeof {
   // the use as an extension.
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
-  _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Winvalid-offsetof")
   static const size_t value = offsetof(_FirstPaddingByte<>, __first_padding_byte_);
   _LIBCPP_DIAGNOSTIC_POP
 };

>From 8c8a7fae298c412a622a485517d01694593b1c81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Sat, 21 Oct 2023 14:10:41 +0200
Subject: [PATCH 16/31] rename __expected_repr to __repr

---
 libcxx/include/__expected/expected.h | 66 ++++++++++++++--------------
 1 file changed, 33 insertions(+), 33 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index d8f0c97c5f9ff9f..6be4617f07c8b27 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -862,7 +862,7 @@ class expected {
       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the __expected_repr's destructor handles this
+    // __repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
 
     _ValueType __val_;
@@ -909,7 +909,7 @@ class expected {
       requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the __expected_repr's destructor handles this
+    // __repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
     {}
@@ -918,51 +918,51 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  struct __expected_repr {
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+  struct __repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
         std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
         std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _Args&&... __args)
         : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
 
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
       requires(is_copy_constructible_v<_Tp> &&
                is_copy_constructible_v<_Err> &&
                is_trivially_copy_constructible_v<_Tp> &&
                is_trivially_copy_constructible_v<_Err>)
     = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
       requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
                 && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
     = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
     = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
     {
       if (__has_val_) {
@@ -980,7 +980,7 @@ class expected {
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
-  __expected_repr __repr_;
+  __repr __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -1522,7 +1522,7 @@ class expected<_Tp, _Err> {
       requires(is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the __expected_repr's destructor handles this
+    // __repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
 
     __empty_t __empty_;
@@ -1561,7 +1561,7 @@ class expected<_Tp, _Err> {
       requires(is_trivially_destructible_v<_ErrorType>)
     = default;
 
-    // the __expected_repr's destructor handles this
+    // __repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(!is_trivially_destructible_v<_ErrorType>)
     {}
@@ -1570,40 +1570,40 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
   };
 
-  struct __expected_repr {
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+  struct __repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t) : __union_(), __has_val_(true) {}
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t) : __union_(), __has_val_(true) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
         std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
         : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
     template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _Args&&... __args)
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _Args&&... __args)
         : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
 
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
       requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
     = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
       requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
     = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(is_trivially_destructible_v<_Err>)
     = default;
 
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(!is_trivially_destructible_v<_Err>)
     {
       if (!__has_val_) {
@@ -1619,7 +1619,7 @@ class expected<_Tp, _Err> {
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
-  __expected_repr __repr_;
+  __repr __repr_;
 };
 
 _LIBCPP_END_NAMESPACE_STD

>From bf2dd26610336bc9f0ee2279a4a71b37fe3b7d14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Tue, 24 Oct 2023 16:52:35 +0200
Subject: [PATCH 17/31] implement optimized layout for types without tail
 padding

---
 libcxx/include/__expected/expected.h          | 1120 ++++++++++-------
 .../no_unique_address.compile.pass.cpp        |   22 +-
 .../transform_error.mandates.verify.cpp       |    1 +
 .../no_unique_address.compile.pass.cpp        |   19 +-
 .../transform_error.mandates.verify.cpp       |    2 +
 5 files changed, 724 insertions(+), 440 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 6be4617f07c8b27..acc68f9546548b2 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -88,8 +88,288 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
+template <class _Union, class _OtherUnion>
+_LIBCPP_HIDE_FROM_ABI constexpr _Union __make_expected_union(bool __has_val, _OtherUnion&& __other)
+{
+  if (__has_val)
+    return _Union(in_place, std::forward<_OtherUnion>(__other).__val_);
+  else
+    return _Union(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+}
+
+template <class _ValueType, class _ErrorType>
+union __expected_union_t {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(in_place_t, _Args&&... __args)
+      : __val_(std::forward<_Args>(__args)...) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(unexpect_t, _Args&&... __args)
+      : __unex_(std::forward<_Args>(__args)...) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
+      std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
+      std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t()
+    requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
+  = default;
+
+  // __expected_repr's destructor handles this
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t() {}
+
+  // XXX Why are those not [[no_unique_address]]?
+  _ValueType __val_;
+  _ErrorType __unex_;
+};
+
+// use named union because [[no_unique_address]] cannot be applied to an unnamed union,
+// also guaranteed elision into a potentially-overlapping subobject is unsettled (and
+// it's not clear that it's implementable, given that the function is allowed to clobber
+// the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
+template <class _ValueType, class _ErrorType>
+  requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
+union __expected_union_t<_ValueType, _ErrorType> {
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_union_t(const __expected_union_t&) = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_union_t& operator=(const __expected_union_t&) = default;
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(in_place_t, _Args&&... __args)
+      : __val_(std::forward<_Args>(__args)...) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(unexpect_t, _Args&&... __args)
+      : __unex_(std::forward<_Args>(__args)...) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
+      std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
+      std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t()
+    requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
+  = default;
+
+  // __expected_repr's destructor handles this
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t() {}
+
+  _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
+  _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
+};
+
+template <class _Tp, class _Err, bool _StuffTail = false>
+struct __expected_repr {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+      std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _OtherUnion&& __other)
+      : __union_(__make_expected_union<__expected_union_t<_Tp, _Err>>(__has_val,
+            std::forward<_OtherUnion>(__other))),
+        __has_val_(__has_val) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+    requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
+             is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
+  = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+    requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
+             is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+  {
+    __destroy_union_member();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+  {
+    std::destroy_at(&__union_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+  {
+    __destroy_union_member();
+    std::destroy_at(&__union_);
+  }
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t, _Args&&... __args)
+  {
+    std::construct_at(&__union_, in_place, std::forward<_Args>(__args)...);
+    __has_val_ = true;
+  }
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
+  {
+    std::construct_at(&__union_, unexpect, std::forward<_Args>(__args)...);
+    __has_val_ = false;
+  }
+
+private:
+  template <class, class>
+  friend class expected;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
+    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+  {
+    if (__has_val_) {
+      std::destroy_at(std::addressof(__union_.__val_));
+    } else {
+      std::destroy_at(std::addressof(__union_.__unex_));
+    }
+  }
+
+  __expected_union_t<_Tp, _Err> __union_;
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+};
+
+template <class _Tp, class _Err>
+struct __expected_repr<_Tp, _Err, true> {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+      std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
+      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _OtherUnion&& __other)
+      : __union_(__make_expected_union<__expected_union_t<_Tp, _Err>>(__has_val,
+            std::forward<_OtherUnion>(__other))),
+        __has_val_(__has_val) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
+    requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
+             is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
+  = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
+    requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
+             is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
+    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+  {
+    if (__has_val_) {
+      std::destroy_at(std::addressof(__union_.__val_));
+    } else {
+      std::destroy_at(std::addressof(__union_.__unex_));
+    }
+  }
+
+private:
+  template <class, class>
+  friend class expected;
+
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_union_t<_Tp, _Err> __union_;
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+};
+
+template <class _Tp, class _Err>
+struct __expected_base {
+protected:
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
+      : __repr_(std::forward<_Args>(__args)...) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
+    __repr_.__destroy_union();
+  }
+
+  template <class _Tag, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
+  {
+    __repr_.__construct_union(__tag, std::forward<_Args>(__args)...);
+  }
+
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_repr<_Tp, _Err, false> __repr_;
+};
+
+template <class _Tp, class _Err>
+    requires (sizeof(__expected_repr<_Tp, _Err, true>) == sizeof(__expected_union_t<_Tp, _Err>))
+struct __expected_base<_Tp, _Err> {
+protected:
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
+      : __repr_(std::forward<_Args>(__args)...) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
+    std::destroy_at(&__repr_);
+  }
+
+  template <class _Tag, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
+  {
+    std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
+  }
+
+  __expected_repr<_Tp, _Err, true> __repr_;
+};
+
 template <class _Tp, class _Err>
-class expected {
+class expected : private __expected_base<_Tp, _Err> {
   static_assert(
       !is_reference_v<_Tp> &&
           !is_function_v<_Tp> &&
@@ -107,6 +387,8 @@ class expected {
   template <class _Up, class _OtherErr>
   friend class expected;
 
+  using __base = __expected_base<_Tp, _Err>;
+
 public:
   using value_type      = _Tp;
   using error_type      = _Err;
@@ -119,22 +401,20 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI constexpr expected()
     noexcept(is_nothrow_default_constructible_v<_Tp>) // strengthened
     requires is_default_constructible_v<_Tp>
-      : __repr_(in_place) {}
+      : __base(in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&)
-    requires(is_copy_constructible_v<_Tp> &&
-             is_copy_constructible_v<_Err> &&
-             is_trivially_copy_constructible_v<_Tp> &&
-             is_trivially_copy_constructible_v<_Err>)
+    requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
+             is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
   = default;
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __other)
     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
-      : __repr_(__other.__repr_.__has_val_, __other.__repr_.__union_) { }
+      : __base(__other.__repr_.__has_val_, __other.__repr_.__union_) { }
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
@@ -145,7 +425,7 @@ class expected {
     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
-      : __repr_(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) { }
+      : __base(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) { }
 
 private:
   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
@@ -170,12 +450,12 @@ class expected {
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_in_place_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+      : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       std::__expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+      : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
 public:
   template <class _Up, class _OtherErr>
@@ -185,14 +465,14 @@ class expected {
   expected(const expected<_Up, _OtherErr>& __other)
     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(__other.__repr_.__has_val_, __other.__repr_.__union_) {}
+      : __base(__other.__repr_.__has_val_, __other.__repr_.__union_) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __other)
     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) {}
+      : __base(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) {}
 
   template <class _Up = _Tp>
     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
@@ -200,47 +480,47 @@ class expected {
              (!is_same_v<remove_cv_t<_Tp>, bool> || !__is_std_expected<remove_cvref_t<_Up>>::value))
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp>)
       expected(_Up&& __u) noexcept(is_nothrow_constructible_v<_Tp, _Up>) // strengthened
-      : __repr_(in_place, std::forward<_Up>(__u)) {}
+      : __base(in_place, std::forward<_Up>(__u)) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(unexpect, __unex.error()) {}
+      : __base(unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(unexpect, std::move(__unex.error())) {}
+      : __base(unexpect, std::move(__unex.error())) {}
 
   template <class... _Args>
     requires is_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, _Args...>) // strengthened
-      : __repr_(in_place, std::forward<_Args>(__args)...) {}
+      : __base(in_place, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(in_place, __il, std::forward<_Args>(__args)...) {}
+      : __base(in_place, __il, std::forward<_Args>(__args)...) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_(unexpect, std::forward<_Args>(__args)...) {}
+      : __base(unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit
   expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(unexpect, __il, std::forward<_Args>(__args)...) {}
+      : __base(unexpect, __il, std::forward<_Args>(__args)...) {}
 
   // [expected.object.dtor], destructor
 
@@ -250,22 +530,21 @@ class expected {
   template <class _Tag, class _OtherTag, class _T1, class _T2, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(_T2& __oldval, _Args&&... __args) {
     if constexpr (is_nothrow_constructible_v<_T1, _Args...>) {
-      std::destroy_at(&__repr_);
-      std::construct_at(&__repr_, _Tag{}, std::forward<_Args>(__args)...);
+      this->__destroy();
+      this->__construct(_Tag{}, std::forward<_Args>(__args)...);
     } else if constexpr (is_nothrow_move_constructible_v<_T1>) {
       _T1 __tmp(std::forward<_Args>(__args)...);
-      std::destroy_at(&__repr_);
-      std::construct_at(&__repr_, _Tag{}, std::move(__tmp));
+      this->__destroy();
+      this->__construct(_Tag{}, std::move(__tmp));
     } else {
       static_assert(
           is_nothrow_move_constructible_v<_T2>,
           "To provide strong exception guarantee, T2 has to satisfy `is_nothrow_move_constructible_v` so that it can "
           "be reverted to the previous state in case an exception is thrown during the assignment.");
       _T2 __tmp(std::move(__oldval));
-      std::destroy_at(&__repr_);
-      auto __trans =
-          std::__make_exception_guard([&] { std::construct_at(&__repr_, _OtherTag{}, std::move(__tmp)); });
-      std::construct_at(&__repr_, _Tag{}, std::forward<_Args>(__args)...);
+      this->__destroy();
+      auto __trans = std::__make_exception_guard([&] { this->__construct(_OtherTag{}, std::move(__tmp)); });
+      this->__construct(_Tag{}, std::forward<_Args>(__args)...);
       __trans.__complete();
     }
   }
@@ -286,16 +565,16 @@ class expected {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
-      __repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
-    } else if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
+      this->__repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
+    } else if (this->__repr_.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          __repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
+          this->__repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
     } else if (__rhs.__repr_.__has_val_) {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          __repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
+          this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
     } else {
-      __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
+      this->__repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
     }
     return *this;
   }
@@ -312,16 +591,16 @@ class expected {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
-      __repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
-    } else if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
+      this->__repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
+    } else if (this->__repr_.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          __repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
+          this->__repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
     } else if (__rhs.__repr_.__has_val_) {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          __repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
+          this->__repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
     } else {
-      __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
+      this->__repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
     }
     return *this;
   }
@@ -336,11 +615,11 @@ class expected {
               is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (__repr_.__has_val_) {
-      __repr_.__union_.__val_ = std::forward<_Up>(__v);
+    if (this->__repr_.__has_val_) {
+      this->__repr_.__union_.__val_ = std::forward<_Up>(__v);
     } else {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          __repr_.__union_.__unex_, std::forward<_Up>(__v));
+          this->__repr_.__union_.__unex_, std::forward<_Up>(__v));
     }
     return *this;
   }
@@ -359,11 +638,11 @@ class expected {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          __repr_.__union_.__val_, __un.error());
+          this->__repr_.__union_.__val_, __un.error());
     } else {
-      __repr_.__union_.__unex_ = __un.error();
+      this->__repr_.__union_.__unex_ = __un.error();
     }
     return *this;
   }
@@ -371,11 +650,11 @@ class expected {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          __repr_.__union_.__val_, std::move(__un.error()));
+          this->__repr_.__union_.__val_, std::move(__un.error()));
     } else {
-      __repr_.__union_.__unex_ = std::move(__un.error());
+      this->__repr_.__union_.__unex_ = std::move(__un.error());
     }
     return *this;
   }
@@ -383,20 +662,19 @@ class expected {
   template <class... _Args>
     requires is_nothrow_constructible_v<_Tp, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
-    std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, in_place, std::forward<_Args>(__args)...);
+    this->__destroy();
+    this->__construct(in_place, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
   template <class _Up, class... _Args>
     requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
-    std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, in_place, __il, std::forward<_Args>(__args)...);
+    this->__destroy();
+    this->__construct(in_place, __il, std::forward<_Args>(__args)...);
     return __repr_.__union_.__val_;
   }
 
-
 public:
   // [expected.object.swap], swap
   _LIBCPP_HIDE_FROM_ABI constexpr void swap(expected& __rhs)
@@ -414,34 +692,34 @@ class expected {
     auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       if constexpr (is_nothrow_move_constructible_v<_Err>) {
         _Err __tmp(std::move(__with_err.__repr_.__union_.__unex_));
-        std::destroy_at(&__with_err.__repr_);
+        __with_err.__destroy();
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(&__with_err.__repr_, unexpect, std::move(__tmp));
+          __with_err.__construct(unexpect, std::move(__tmp));
         });
-        std::construct_at(&__with_err.__repr_, in_place, std::move(__with_val.__repr_.__union_.__val_));
+        __with_err.__construct(in_place, std::move(__with_val.__repr_.__union_.__val_));
         __trans.__complete();
-        std::destroy_at(&__with_val.__repr_);
-        std::construct_at(&__with_val.__repr_, unexpect, std::move(__tmp));
+        __with_val.__destroy();
+        __with_val.__construct(unexpect, std::move(__tmp));
       } else {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
         _Tp __tmp(std::move(__with_val.__repr_.__union_.__val_));
-        std::destroy_at(&__with_val.__repr_);
+        __with_val.__destroy();
         auto __trans = std::__make_exception_guard([&] {
-          std::construct_at(&__with_val.__repr_, in_place, std::move(__tmp));
+          __with_val.__construct(in_place, std::move(__tmp));
         });
-        std::construct_at(&__with_val.__repr_, unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+        __with_val.__construct(unexpect, std::move(__with_err.__repr_.__union_.__unex_));
         __trans.__complete();
-        std::destroy_at(&__with_err.__repr_);
-        std::construct_at(&__with_err.__repr_, in_place, std::move(__tmp));
+        __with_err.__destroy();
+        __with_err.__construct(in_place, std::move(__tmp));
       }
     };
 
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       if (__rhs.__repr_.__has_val_) {
         using std::swap;
-        swap(__repr_.__union_.__val_, __rhs.__repr_.__union_.__val_);
+        swap(this->__repr_.__union_.__val_, __rhs.__repr_.__union_.__val_);
       } else {
         __swap_val_unex_impl(*this, __rhs);
       }
@@ -450,7 +728,7 @@ class expected {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
+        swap(this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
       }
     }
   }
@@ -464,105 +742,105 @@ class expected {
 
   // [expected.object.obs], observers
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return __repr_.__union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return this->__repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return __repr_.__union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return this->__repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(this->__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(this->__repr_.__union_.__val_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__has_val_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__has_val_; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!__repr_.__has_val_) {
+    if (!this->__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return __repr_.__union_.__val_;
+    return this->__repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!__repr_.__has_val_) {
+    if (!this->__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return __repr_.__union_.__val_;
+    return this->__repr_.__union_.__val_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!__repr_.__has_val_) {
+    if (!this->__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(__repr_.__union_.__val_);
+    return std::move(this->__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!__repr_.__has_val_) {
+    if (!this->__repr_.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(__repr_.__union_.__val_);
+    return std::move(this->__repr_.__union_.__val_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return __repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return __repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__union_.__unex_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__union_.__unex_);
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return __repr_.__has_val_ ? __repr_.__union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__repr_.__has_val_ ? this->__repr_.__union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return __repr_.__has_val_ ? std::move(__repr_.__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__repr_.__has_val_ ? std::move(this->__repr_.__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up = _Err>
@@ -592,7 +870,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
     }
     return _Up(unexpect, error());
   }
@@ -605,7 +883,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
     }
     return _Up(unexpect, error());
   }
@@ -619,7 +897,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -633,7 +911,7 @@ class expected {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -646,7 +924,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, __repr_.__union_.__val_);
+      return _Gp(in_place, this->__repr_.__union_.__val_);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -659,7 +937,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, __repr_.__union_.__val_);
+      return _Gp(in_place, this->__repr_.__union_.__val_);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -673,7 +951,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(__repr_.__union_.__val_));
+      return _Gp(in_place, std::move(this->__repr_.__union_.__val_));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -687,7 +965,7 @@ class expected {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(__repr_.__union_.__val_));
+      return _Gp(in_place, std::move(this->__repr_.__union_.__val_));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -700,9 +978,9 @@ class expected {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __repr_.__union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__repr_.__union_.__val_);
     } else {
-      std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
+      std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
       return expected<_Up, _Err>();
     }
   }
@@ -715,9 +993,9 @@ class expected {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), __repr_.__union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__repr_.__union_.__val_);
     } else {
-      std::invoke(std::forward<_Func>(__f), __repr_.__union_.__val_);
+      std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
       return expected<_Up, _Err>();
     }
   }
@@ -731,9 +1009,9 @@ class expected {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
       return expected<_Up, _Err>();
     }
   }
@@ -747,9 +1025,9 @@ class expected {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(__repr_.__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
       return expected<_Up, _Err>();
     }
   }
@@ -761,7 +1039,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, __repr_.__union_.__val_);
+      return expected<_Tp, _Gp>(in_place, this->__repr_.__union_.__val_);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -773,7 +1051,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, __repr_.__union_.__val_);
+      return expected<_Tp, _Gp>(in_place, this->__repr_.__union_.__val_);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -785,7 +1063,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(__repr_.__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__union_.__val_));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -798,7 +1076,7 @@ class expected {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(__repr_.__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__union_.__val_));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -828,164 +1106,260 @@ class expected {
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
     return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __e.error());
   }
+};
+
+struct __expected_empty_t {};
+
+template <class _Union, class _OtherUnion>
+_LIBCPP_HIDE_FROM_ABI constexpr _Union __make_expected_void_union(bool __has_val, _OtherUnion&& __other)
+{
+  if (__has_val)
+    return _Union(in_place);
+  else
+    return _Union(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+}
+
+template <class _ErrorType>
+union __expected_void_union_t {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(in_place_t) : __empty_() {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(unexpect_t, _Args&&... __args)
+      : __unex_(std::forward<_Args>(__args)...) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(
+      __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
+    requires(is_trivially_destructible_v<_ErrorType>)
+  = default;
+
+  // __expected_repr's destructor handles this
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t() {}
+
+  // XXX: Why are those not [[no_unique_address]]?
+  __expected_empty_t __empty_;
+  _ErrorType __unex_;
+};
+
+// use named union because [[no_unique_address]] cannot be applied to an unnamed union,
+// also guaranteed elision into a potentially-overlapping subobject is unsettled (and
+// it's not clear that it's implementable, given that the function is allowed to clobber
+// the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
+template <class _ErrorType>
+  requires is_trivially_move_constructible_v<_ErrorType>
+union __expected_void_union_t<_ErrorType> {
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_union_t(const __expected_void_union_t&) = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_union_t& operator=(const __expected_void_union_t&) = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(in_place_t) : __empty_() {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(unexpect_t, _Args&&... __args)
+      : __unex_(std::forward<_Args>(__args)...) {}
+
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(
+      __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
+    requires(is_trivially_destructible_v<_ErrorType>)
+  = default;
+
+  // __expected_repr's destructor handles this
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
+    requires(!is_trivially_destructible_v<_ErrorType>)
+  {}
+
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_empty_t __empty_;
+  _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
+};
+
+template <class _Err, bool _StuffTail = false>
+struct __expected_void_repr {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr() = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(in_place_t __tag)
+      : __union_(__tag), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(unexpect_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(
+      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(bool __has_val, _OtherUnion&& __other)
+      : __union_(__make_expected_void_union<__expected_void_union_t<_Err>>(__has_val,
+            std::forward<_OtherUnion>(__other))),
+        __has_val_(__has_val) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
+    requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
+  = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&)
+    requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr& operator=(const __expected_void_repr&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
+    requires(is_trivially_destructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
+    requires(!is_trivially_destructible_v<_Err>)
+  {
+    __destroy_union_member();
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+    requires(is_trivially_destructible_v<_Err>)
+  {
+    std::destroy_at(&__union_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+    requires(!is_trivially_destructible_v<_Err>)
+  {
+    __destroy_union_member();
+    std::destroy_at(&__union_);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t)
+  {
+    std::construct_at(&__union_, in_place);
+    __has_val_ = true;
+  }
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
+  {
+    std::construct_at(&__union_, unexpect, std::forward<_Args>(__args)...);
+    __has_val_ = false;
+  }
 
 private:
-  template <class _ValueType, class _ErrorType>
-  union __union_t {
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
-        : __val_(std::forward<_Args>(__args)...) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
-        : __unex_(std::forward<_Args>(__args)...) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Union>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
-      if (__has_val)
-        std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
-      else
-        std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
-    }
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
-    = default;
-
-    // __repr's destructor handles this
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
-
-    _ValueType __val_;
-    _ErrorType __unex_;
-  };
-
-  // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
-  // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
-  // it's not clear that it's implementable, given that the function is allowed to clobber
-  // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
-  template <class _ValueType, class _ErrorType>
-    requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
-  union __union_t<_ValueType, _ErrorType> {
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
-        : __val_(std::forward<_Args>(__args)...) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
-        : __unex_(std::forward<_Args>(__args)...) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Union>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
-      if (__has_val)
-        std::construct_at(std::addressof(__val_), std::forward<_Union>(__other).__val_);
-      else
-        std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
-    }
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
-    = default;
-
-    // __repr's destructor handles this
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(!is_trivially_destructible_v<_ValueType> || !is_trivially_destructible_v<_ErrorType>)
-    {}
-
-    _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
-    _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
-  };
-
-  struct __repr {
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
-        std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
-        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _Args&&... __args)
-        : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
-
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
-      requires(is_copy_constructible_v<_Tp> &&
-               is_copy_constructible_v<_Err> &&
-               is_trivially_copy_constructible_v<_Tp> &&
-               is_trivially_copy_constructible_v<_Err>)
-    = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
-      requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
-                && is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
-    = default;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
-      requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
-    = default;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
-      requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
-    {
-      if (__has_val_) {
-        std::destroy_at(std::addressof(__union_.__val_));
-      } else {
-        std::destroy_at(std::addressof(__union_.__unex_));
-      }
+  template <class, class>
+  friend class expected;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
+    requires(!is_trivially_destructible_v<_Err>)
+  {
+    if (!__has_val_) {
+      std::destroy_at(std::addressof(__union_.__unex_));
+    }
+  }
+
+  __expected_void_union_t<_Err> __union_;
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+};
+
+template <class _Err>
+struct __expected_void_repr<_Err, true> {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr() = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(in_place_t __tag)
+      : __union_(__tag), __has_val_(true) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(unexpect_t __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(
+      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(bool __has_val, _OtherUnion&& __other)
+      : __union_(__make_expected_void_union<__expected_void_union_t<_Err>>(__has_val,
+            std::forward<_OtherUnion>(__other))),
+        __has_val_(__has_val) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
+    requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
+  = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&) = delete;
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&)
+    requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr& operator=(const __expected_void_repr&) = delete;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
+    requires(is_trivially_destructible_v<_Err>)
+  = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
+    requires(!is_trivially_destructible_v<_Err>)
+  {
+    if (!__has_val_) {
+      std::destroy_at(std::addressof(__union_.__unex_));
     }
+  }
+
+private:
+  template <class, class>
+  friend class expected;
+
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_void_union_t<_Err> __union_;
+  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+};
+
+template <class _Err>
+struct __expected_void_base {
+protected:
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args)
+      : __repr_(std::forward<_Args>(__args)...) {}
+
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
+    __repr_.__destroy_union();
+  }
+
+  template <class _Tag, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
+  {
+    __repr_.__construct_union(__tag, std::forward<_Args>(__args)...);
+  }
+
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_void_repr<_Err, false> __repr_;
+};
+
+template <class _Err>
+    requires (sizeof(__expected_void_repr<_Err, true>) == sizeof(__expected_void_union_t<_Err>))
+struct __expected_void_base<_Err> {
+protected:
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args)
+      : __repr_(std::forward<_Args>(__args)...) {}
 
-  private:
-    template <class, class>
-    friend class expected;
+  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
+    std::destroy_at(&__repr_);
+  }
 
-    _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Tp, _Err> __union_;
-    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-  };
+  template <class _Tag, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
+  {
+    std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
+  }
 
-  __repr __repr_;
+  __expected_void_repr<_Err, true> __repr_;
 };
 
 template <class _Tp, class _Err>
   requires is_void_v<_Tp>
-class expected<_Tp, _Err> {
+class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   static_assert(__valid_std_unexpected<_Err>::value,
                 "[expected.void.general] A program that instantiates expected<T, E> with a E that is not a "
                 "valid argument for unexpected<E> is ill-formed");
@@ -1002,6 +1376,8 @@ class expected<_Tp, _Err> {
             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>&>>,
             _Not<is_constructible<unexpected<_Err>, const expected<_Up, _OtherErr>>>>;
 
+  using __base = __expected_void_base<_Err>;
+
 public:
   using value_type      = _Tp;
   using error_type      = _Err;
@@ -1011,7 +1387,7 @@ class expected<_Tp, _Err> {
   using rebind = expected<_Up, error_type>;
 
   // [expected.void.ctor], constructors
-  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __repr_(in_place) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr expected() noexcept : __base(in_place) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected&) = delete;
 
@@ -1022,7 +1398,7 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
     noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
-      : __repr_(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
+      : __base(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
@@ -1031,55 +1407,55 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
     noexcept(is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
-      : __repr_(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
+      : __base(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const expected<_Up, _OtherErr>& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
+      : __base(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
+      : __base(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const unexpected<_OtherErr>& __unex)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __repr_(unexpect, __unex.error()) {}
+      : __base(unexpect, __unex.error()) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, _OtherErr>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(unexpected<_OtherErr>&& __unex)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __repr_(unexpect, std::move(__unex.error())) {}
+      : __base(unexpect, std::move(__unex.error())) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __repr_(in_place) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(in_place_t) noexcept : __base(in_place) {}
 
   template <class... _Args>
     requires is_constructible_v<_Err, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, _Args...>) // strengthened
-      : __repr_(unexpect, std::forward<_Args>(__args)...) {}
+      : __base(unexpect, std::forward<_Args>(__args)...) {}
 
   template <class _Up, class... _Args>
     requires is_constructible_v< _Err, initializer_list<_Up>&, _Args... >
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(unexpect_t, initializer_list<_Up> __il, _Args&&... __args)
     noexcept(is_nothrow_constructible_v<_Err, initializer_list<_Up>&, _Args...>) // strengthened
-      : __repr_(unexpect, __il, std::forward<_Args>(__args)...) {}
+      : __base(unexpect, __il, std::forward<_Args>(__args)...) {}
 
 private:
   template <class _Func, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit expected(
       __expected_construct_unexpected_from_invoke_tag __tag, _Func&& __f, _Args&&... __args)
-      : __repr_(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+      : __base(__tag, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
 public:
   // [expected.void.dtor], destructor
@@ -1090,17 +1466,16 @@ class expected<_Tp, _Err> {
   // precondition: has_value()
   template <class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(unexpect_t, _Args&&... __args) {
-    std::destroy_at(&__repr_);
-    auto __trans =
-        std::__make_exception_guard([&] { std::construct_at(&__repr_, in_place); });
-    std::construct_at(&__repr_, unexpect, std::forward<_Args>(__args)...);
+    this->__destroy();
+    auto __trans = std::__make_exception_guard([&] { this->__construct(in_place); });
+    this->__construct(unexpect, std::forward<_Args>(__args)...);
     __trans.__complete();
   }
 
   // precondition: !has_value()
   _LIBCPP_HIDE_FROM_ABI constexpr void __reinit_expected(in_place_t) {
-    std::destroy_at(&__repr_);
-    std::construct_at(&__repr_, in_place);
+    this->__destroy();
+    this->__construct(in_place);
   }
 
 public:
@@ -1111,7 +1486,7 @@ class expected<_Tp, _Err> {
     noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
   {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
         __reinit_expected(unexpect, __rhs.__repr_.__union_.__unex_);
       }
@@ -1119,7 +1494,7 @@ class expected<_Tp, _Err> {
       if (__rhs.__repr_.__has_val_) {
         __reinit_expected(in_place);
       } else {
-        __repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
+        this->__repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
       }
     }
     return *this;
@@ -1133,7 +1508,7 @@ class expected<_Tp, _Err> {
     requires(is_move_assignable_v<_Err> &&
              is_move_constructible_v<_Err>)
   {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
         __reinit_expected(unexpect, std::move(__rhs.__repr_.__union_.__unex_));
       }
@@ -1141,7 +1516,7 @@ class expected<_Tp, _Err> {
       if (__rhs.__repr_.__has_val_) {
         __reinit_expected(in_place);
       } else {
-        __repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
+        this->__repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
       }
     }
     return *this;
@@ -1150,10 +1525,10 @@ class expected<_Tp, _Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       __reinit_expected(unexpect, __un.error());
     } else {
-      __repr_.__union_.__unex_ = __un.error();
+      this->__repr_.__union_.__unex_ = __un.error();
     }
     return *this;
   }
@@ -1161,16 +1536,16 @@ class expected<_Tp, _Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       __reinit_expected(unexpect, std::move(__un.error()));
     } else {
-      __repr_.__union_.__unex_ = std::move(__un.error());
+      this->__repr_.__union_.__unex_ = std::move(__un.error());
     }
     return *this;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
-    if (!__repr_.__has_val_) {
+    if (!this->__repr_.__has_val_) {
       __reinit_expected(in_place);
     }
   }
@@ -1187,7 +1562,7 @@ class expected<_Tp, _Err> {
       __with_err.__reinit_expected(in_place);
     };
 
-    if (__repr_.__has_val_) {
+    if (this->__repr_.__has_val_) {
       if (!__rhs.__repr_.__has_val_) {
         __swap_val_unex_impl(*this, __rhs);
       }
@@ -1196,7 +1571,7 @@ class expected<_Tp, _Err> {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
+        swap(this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
       }
     }
   }
@@ -1209,44 +1584,44 @@ class expected<_Tp, _Err> {
   }
 
   // [expected.void.obs], observers
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__has_val_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__has_val_; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
-    if (!__repr_.__has_val_) {
-      std::__throw_bad_expected_access<_Err>(__repr_.__union_.__unex_);
+    if (!this->__repr_.__has_val_) {
+      std::__throw_bad_expected_access<_Err>(this->__repr_.__union_.__unex_);
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
-    if (!__repr_.__has_val_) {
-      std::__throw_bad_expected_access<_Err>(std::move(__repr_.__union_.__unex_));
+    if (!this->__repr_.__has_val_) {
+      std::__throw_bad_expected_access<_Err>(std::move(this->__repr_.__union_.__unex_));
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return __repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return __repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__union_.__unex_;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__union_.__unex_);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__union_.__unex_);
   }
 
   template <class _Up = _Err>
@@ -1493,133 +1868,6 @@ class expected<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
     return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __y.error());
   }
-
-private:
-  struct __empty_t {};
-
-  template <class _ErrorType>
-  union __union_t {
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
-        : __unex_(std::forward<_Args>(__args)...) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Union>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
-      if (__has_val)
-        std::construct_at(std::addressof(__empty_));
-      else
-        std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
-    }
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(is_trivially_destructible_v<_ErrorType>)
-    = default;
-
-    // __repr's destructor handles this
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
-
-    __empty_t __empty_;
-    _ErrorType __unex_;
-  };
-
-  // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
-  // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
-  // it's not clear that it's implementable, given that the function is allowed to clobber
-  // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
-  template <class _ErrorType>
-    requires is_trivially_move_constructible_v<_ErrorType>
-  union __union_t<_ErrorType> {
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t() : __empty_() {}
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = default;
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
-        : __unex_(std::forward<_Args>(__args)...) {}
-
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
-        __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-    template <class _Union>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(bool __has_val, _Union&& __other) {
-      if (__has_val)
-        std::construct_at(std::addressof(__empty_));
-      else
-        std::construct_at(std::addressof(__unex_), std::forward<_Union>(__other).__unex_);
-    }
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(is_trivially_destructible_v<_ErrorType>)
-    = default;
-
-    // __repr's destructor handles this
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
-      requires(!is_trivially_destructible_v<_ErrorType>)
-    {}
-
-    _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
-    _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
-  };
-
-  struct __repr {
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t) : __union_(), __has_val_(true) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
-        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _Args&&... __args)
-        : __union_(__has_val, std::forward<_Args>(__args)...), __has_val_(__has_val) {}
-
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
-      requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
-    = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
-      requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
-    = default;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
-      requires(is_trivially_destructible_v<_Err>)
-    = default;
-
-    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
-      requires(!is_trivially_destructible_v<_Err>)
-    {
-      if (!__has_val_) {
-        std::destroy_at(std::addressof(__union_.__unex_));
-      }
-    }
-
-  private:
-    template <class, class>
-    friend class expected;
-
-    _LIBCPP_NO_UNIQUE_ADDRESS __union_t<_Err> __union_;
-    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-  };
-
-  __repr __repr_;
 };
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index 8eeec70ff0e4243..a7ddd13e7930aa1 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -13,6 +13,7 @@
 // test [[no_unique_address]] is applied to the union
 
 #include <expected>
+#include <optional>
 #include <memory>
 
 struct Empty {};
@@ -50,5 +51,22 @@ static_assert(sizeof(std::expected<Empty, BoolWithPadding>) ==
 
 // In this case, there should be tail padding in the `expected` because `A`
 // itself does _not_ have tail padding.
-// XXX
-// static_assert(sizeof(std::expected<A, A>) > std::__libcpp_datasizeof<std::expected<A, A>>::value);
+static_assert(sizeof(std::expected<A, A>) > std::__libcpp_datasizeof<std::expected<A, A>>::value);
+
+// Test with some real types.
+static_assert(sizeof(std::expected<std::optional<int>, int>) == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<std::optional<int>, int>>::value == 8);
+
+static_assert(sizeof(std::expected<int, std::optional<int>>) == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<int, std::optional<int>>>::value == 8);
+
+static_assert(sizeof(std::expected<int, int>) == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<int, int>>::value == 5);
+
+// clang-format off
+static_assert(std::__libcpp_datasizeof<int>::value == 4);
+static_assert(std::__libcpp_datasizeof<std::expected<int, int>>::value == 5);
+static_assert(std::__libcpp_datasizeof<std::expected<std::expected<int, int>, int>>::value == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<std::expected<std::expected<int, int>, int>, int>>::value == 9);
+static_assert(std::__libcpp_datasizeof<std::expected<std::expected<std::expected<std::expected<int, int>, int>, int>, int>>::value == 12);
+// clang-format on
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 965e82a7b403465..16faddb280d3a33 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -48,6 +48,7 @@ void test() {
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
+    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index 2129aa7b2405c7e..fe4ef4f1e0e2389 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -13,6 +13,7 @@
 // test [[no_unique_address]] is applied to the union
 
 #include <expected>
+#include <optional>
 #include <memory>
 
 struct Empty {};
@@ -44,5 +45,19 @@ static_assert(sizeof(std::expected<void, BoolWithPadding>) ==
 
 // In this case, there should be tail padding in the `expected` because `A`
 // itself does _not_ have tail padding.
-// XXX
-// static_assert(sizeof(std::expected<void, A>) > std::__libcpp_datasizeof<std::expected<void, A>>::value);
+static_assert(sizeof(std::expected<void, A>) > std::__libcpp_datasizeof<std::expected<void, A>>::value);
+
+// Test with some real types.
+static_assert(sizeof(std::expected<void, std::optional<int>>) == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<void, std::optional<int>>>::value == 8);
+
+static_assert(sizeof(std::expected<void, int>) == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<void, int>>::value == 5);
+
+// clang-format off
+static_assert(std::__libcpp_datasizeof<int>::value == 4);
+static_assert(std::__libcpp_datasizeof<std::expected<void, int>>::value == 5);
+static_assert(std::__libcpp_datasizeof<std::expected<void, std::expected<void, int>>>::value == 8);
+static_assert(std::__libcpp_datasizeof<std::expected<void, std::expected<void, std::expected<void, int>>>>::value == 9);
+static_assert(std::__libcpp_datasizeof<std::expected<void, std::expected<void, std::expected<void, std::expected<void, int>>>>>::value == 12);
+// clang-format on
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 09aa1332e980005..7687a42cb1a8655 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -48,6 +48,8 @@ void test() {
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
+    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
+    // expected-error-re@*:* {{call to deleted constructor of {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}

>From 0b59a030e0dd01ea2af7529dcea5ec80b2815798 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Tue, 24 Oct 2023 20:09:26 +0200
Subject: [PATCH 18/31] try to make guaranteed copy elision work with GCC

Seems to be related to
<https://github.com/itanium-cxx-abi/cxx-abi/issues/107>
---
 libcxx/include/__expected/expected.h | 96 +++++++++++++++++-----------
 1 file changed, 58 insertions(+), 38 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index acc68f9546548b2..ae670ac1d1a8a0b 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -88,15 +88,6 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-template <class _Union, class _OtherUnion>
-_LIBCPP_HIDE_FROM_ABI constexpr _Union __make_expected_union(bool __has_val, _OtherUnion&& __other)
-{
-  if (__has_val)
-    return _Union(in_place, std::forward<_OtherUnion>(__other).__val_);
-  else
-    return _Union(unexpect, std::forward<_OtherUnion>(__other).__unex_);
-}
-
 template <class _ValueType, class _ErrorType>
 union __expected_union_t {
   template <class... _Args>
@@ -192,9 +183,7 @@ struct __expected_repr {
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_expected_union<__expected_union_t<_Tp, _Err>>(__has_val,
-            std::forward<_OtherUnion>(__other))),
-        __has_val_(__has_val) {}
+      : __union_(__make_union(__has_val, std::forward<_OtherUnion>(__other))), __has_val_(__has_val) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
@@ -260,6 +249,16 @@ struct __expected_repr {
     }
   }
 
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI static constexpr __expected_union_t<_Tp, _Err>
+  __make_union(bool __has_val, _OtherUnion&& __other)
+  {
+    if (__has_val)
+      return __expected_union_t<_Tp, _Err>(in_place, std::forward<_OtherUnion>(__other).__val_);
+    else
+      return __expected_union_t<_Tp, _Err>(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+  }
+
   __expected_union_t<_Tp, _Err> __union_;
   _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
 };
@@ -286,12 +285,6 @@ struct __expected_repr<_Tp, _Err, true> {
       std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
       : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_expected_union<__expected_union_t<_Tp, _Err>>(__has_val,
-            std::forward<_OtherUnion>(__other))),
-        __has_val_(__has_val) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
@@ -355,6 +348,10 @@ struct __expected_base<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
       : __repr_(std::forward<_Args>(__args)...) {}
 
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other)
+      : __repr_(__make_repr(__has_val, std::forward<_OtherUnion>(__other))) {}
+
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
     std::destroy_at(&__repr_);
   }
@@ -365,7 +362,20 @@ struct __expected_base<_Tp, _Err> {
     std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
   }
 
-  __expected_repr<_Tp, _Err, true> __repr_;
+private:
+  using __repr = __expected_repr<_Tp, _Err, true>;
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
+  {
+    if (__has_val)
+      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_);
+    else
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+  }
+
+protected:
+  __repr __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -1110,15 +1120,6 @@ class expected : private __expected_base<_Tp, _Err> {
 
 struct __expected_empty_t {};
 
-template <class _Union, class _OtherUnion>
-_LIBCPP_HIDE_FROM_ABI constexpr _Union __make_expected_void_union(bool __has_val, _OtherUnion&& __other)
-{
-  if (__has_val)
-    return _Union(in_place);
-  else
-    return _Union(unexpect, std::forward<_OtherUnion>(__other).__unex_);
-}
-
 template <class _ErrorType>
 union __expected_void_union_t {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(in_place_t) : __empty_() {}
@@ -1196,9 +1197,7 @@ struct __expected_void_repr {
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_expected_void_union<__expected_void_union_t<_Err>>(__has_val,
-            std::forward<_OtherUnion>(__other))),
-        __has_val_(__has_val) {}
+      : __union_(__make_union(__has_val, std::forward<_OtherUnion>(__other))), __has_val_(__has_val) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
@@ -1259,6 +1258,16 @@ struct __expected_void_repr {
     }
   }
 
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI static constexpr __expected_void_union_t<_Err>
+  __make_union(bool __has_val, _OtherUnion&& __other)
+  {
+    if (__has_val)
+      return __expected_void_union_t<_Err>(in_place);
+    else
+      return __expected_void_union_t<_Err>(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+  }
+
   __expected_void_union_t<_Err> __union_;
   _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
 };
@@ -1279,12 +1288,6 @@ struct __expected_void_repr<_Err, true> {
       std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
       : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_expected_void_union<__expected_void_union_t<_Err>>(__has_val,
-            std::forward<_OtherUnion>(__other))),
-        __has_val_(__has_val) {}
-
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
   _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
     requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
@@ -1344,6 +1347,10 @@ struct __expected_void_base<_Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args)
       : __repr_(std::forward<_Args>(__args)...) {}
 
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(bool __has_val, _OtherUnion&& __other)
+      : __repr_(__make_repr(__has_val, std::forward<_OtherUnion>(__other))) {}
+
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
     std::destroy_at(&__repr_);
   }
@@ -1354,7 +1361,20 @@ struct __expected_void_base<_Err> {
     std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
   }
 
-  __expected_void_repr<_Err, true> __repr_;
+private:
+  using __repr = __expected_void_repr<_Err, true>;
+
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
+  {
+    if (__has_val)
+      return __repr(in_place);
+    else
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+  }
+
+protected:
+  __repr __repr_;
 };
 
 template <class _Tp, class _Err>

>From 08a8eba4758e8690ae48cbfd5f1b59743d7ea280 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Tue, 24 Oct 2023 22:47:14 +0200
Subject: [PATCH 19/31] add includes for datasizeof

---
 .../expected.expected/no_unique_address.compile.pass.cpp         | 1 +
 .../expected/expected.void/no_unique_address.compile.pass.cpp    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index a7ddd13e7930aa1..e316f7a0fc1b1e2 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -12,6 +12,7 @@
 
 // test [[no_unique_address]] is applied to the union
 
+#include <__type_traits/datasizeof.h>
 #include <expected>
 #include <optional>
 #include <memory>
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index fe4ef4f1e0e2389..e764dbd66acaa9a 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -12,6 +12,7 @@
 
 // test [[no_unique_address]] is applied to the union
 
+#include <__type_traits/datasizeof.h>
 #include <expected>
 #include <optional>
 #include <memory>

>From 11555df0766306de8802e33cc1e1d165bbc9ce40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 25 Oct 2023 19:23:18 +0200
Subject: [PATCH 20/31] use std::conditional for conditional
 [[no_unique_address]]

---
 libcxx/include/__expected/expected.h          | 643 ++++++++----------
 .../no_unique_address.compile.pass.cpp        |   6 +-
 .../transform_error.mandates.verify.cpp       |   1 -
 3 files changed, 302 insertions(+), 348 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index ae670ac1d1a8a0b..a09a291de9ff9c1 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -88,261 +88,207 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-template <class _ValueType, class _ErrorType>
-union __expected_union_t {
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(in_place_t, _Args&&... __args)
-      : __val_(std::forward<_Args>(__args)...) {}
+template <class _Tp>
+concept __expected_union_member_no_unique_address = is_nothrow_move_constructible_v<_Tp>;
 
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(unexpect_t, _Args&&... __args)
-      : __unex_(std::forward<_Args>(__args)...) {}
+struct __expected_wrap_invoke_tag {};
 
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
-      std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+template <class _Tp>
+struct __expected_wrap_unique {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_unique(_Args&&... __args)
+      : __v(std::forward<_Args>(__args)...) {}
 
   template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
-      std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t()
-    requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
-  = default;
-
-  // __expected_repr's destructor handles this
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t() {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_unique(
+      __expected_wrap_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-  // XXX Why are those not [[no_unique_address]]?
-  _ValueType __val_;
-  _ErrorType __unex_;
+  _Tp __v;
 };
 
-// use named union because [[no_unique_address]] cannot be applied to an unnamed union,
-// also guaranteed elision into a potentially-overlapping subobject is unsettled (and
-// it's not clear that it's implementable, given that the function is allowed to clobber
-// the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
-template <class _ValueType, class _ErrorType>
-  requires(is_trivially_move_constructible_v<_ValueType> && is_trivially_move_constructible_v<_ErrorType>)
-union __expected_union_t<_ValueType, _ErrorType> {
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_union_t(const __expected_union_t&) = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_union_t& operator=(const __expected_union_t&) = default;
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(in_place_t, _Args&&... __args)
-      : __val_(std::forward<_Args>(__args)...) {}
-
+template <class _Tp>
+struct __expected_wrap_no_unique {
   template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(unexpect_t, _Args&&... __args)
-      : __unex_(std::forward<_Args>(__args)...) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_no_unique(_Args&&... __args)
+      : __v(std::forward<_Args>(__args)...) {}
 
   template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
-      std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_union_t(
-      std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_no_unique(
+      __expected_wrap_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t()
-    requires(is_trivially_destructible_v<_ValueType> && is_trivially_destructible_v<_ErrorType>)
-  = default;
-
-  // __expected_repr's destructor handles this
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_union_t() {}
-
-  _LIBCPP_NO_UNIQUE_ADDRESS _ValueType __val_;
-  _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
+  _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
 };
 
-template <class _Tp, class _Err, bool _StuffTail = false>
-struct __expected_repr {
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
-      std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
-      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_union(__has_val, std::forward<_OtherUnion>(__other))), __has_val_(__has_val) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
-    requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
-             is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
-  = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
-    requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
-             is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
-    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
-    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
-  {
-    __destroy_union_member();
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
-  {
-    std::destroy_at(&__union_);
-  }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
-  {
-    __destroy_union_member();
-    std::destroy_at(&__union_);
-  }
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t, _Args&&... __args)
-  {
-    std::construct_at(&__union_, in_place, std::forward<_Args>(__args)...);
-    __has_val_ = true;
-  }
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
-  {
-    std::construct_at(&__union_, unexpect, std::forward<_Args>(__args)...);
-    __has_val_ = false;
-  }
-
-private:
-  template <class, class>
-  friend class expected;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
-    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
-  {
-    if (__has_val_) {
-      std::destroy_at(std::addressof(__union_.__val_));
-    } else {
-      std::destroy_at(std::addressof(__union_.__unex_));
-    }
-  }
-
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI static constexpr __expected_union_t<_Tp, _Err>
-  __make_union(bool __has_val, _OtherUnion&& __other)
-  {
-    if (__has_val)
-      return __expected_union_t<_Tp, _Err>(in_place, std::forward<_OtherUnion>(__other).__val_);
-    else
-      return __expected_union_t<_Tp, _Err>(unexpect, std::forward<_OtherUnion>(__other).__unex_);
-  }
-
-  __expected_union_t<_Tp, _Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+template <bool _NoUnique, class _Tp>
+struct __expected_conditional_no_unique_address {
+  using __type = std::conditional<_NoUnique,
+      __expected_wrap_no_unique<_Tp>, __expected_wrap_unique<_Tp>>::type;
 };
 
 template <class _Tp, class _Err>
-struct __expected_repr<_Tp, _Err, true> {
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr() = delete;
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(in_place_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(unexpect_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
-      std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_repr(
-      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(const __expected_repr&)
-    requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
-             is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
-  = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr(__expected_repr&&)
-    requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
-             is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_repr& operator=(const __expected_repr&) = delete;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
-    requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_repr()
-    requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+struct __expected_base {
+private:
+  // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
+  // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
+  // it's not clear that it's implementable, given that the function is allowed to clobber
+  // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
+  union __union_t {
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete;
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
+        : __val_(std::forward<_Args>(__args)...) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
+        : __unex_(std::forward<_Args>(__args)...) {}
+
+    template <class _Func, class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
+        std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
+        : __val_(__expected_wrap_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+
+    template <class _Func, class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
+        std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+        : __unex_(__expected_wrap_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+      requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+    = default;
+
+    // __repr's destructor handles this
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
+
+    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+        __expected_union_member_no_unique_address<_Tp>, _Tp>::__type __val_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+        __expected_union_member_no_unique_address<_Err>, _Err>::__type __unex_;
+  };
+
+  _LIBCPP_HIDE_FROM_ABI static constexpr bool __can_stuff_tail()
   {
-    if (__has_val_) {
-      std::destroy_at(std::addressof(__union_.__val_));
-    } else {
-      std::destroy_at(std::addressof(__union_.__unex_));
+    struct __x {
+    private:
+      _LIBCPP_NO_UNIQUE_ADDRESS __union_t __union;
+      _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val;
+    };
+    return sizeof(__x) == sizeof(__union_t);
+  }
+
+  struct __repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
+        std::__expected_construct_in_place_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(true) {}
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
+        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+
+    template <class _OtherUnion>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
+      requires(!__can_stuff_tail())
+        : __union_(__expected_wrap_invoke_tag{},
+              [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
+          __has_val_(__has_val) {}
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
+      requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
+               is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
+      requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
+               is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
+      requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
+    = default;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
+      requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+    {
+      __destroy_union_member();
+    }
+
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+      requires(!__can_stuff_tail() && (is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>))
+    {
+      std::destroy_at(&__union_.__v);
+    }
+
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+      requires(!__can_stuff_tail() && (!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>))
+    {
+      __destroy_union_member();
+      std::destroy_at(&__union_.__v);
+    }
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t, _Args&&... __args)
+      requires(!__can_stuff_tail())
+    {
+      std::construct_at(&__union_.__v, in_place, std::forward<_Args>(__args)...);
+      __has_val_ = true;
+    }
+
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
+      requires(!__can_stuff_tail())
+    {
+      std::construct_at(&__union_.__v, unexpect, std::forward<_Args>(__args)...);
+      __has_val_ = false;
+    }
+
+  private:
+    template <class, class>
+    friend class expected;
+
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
+      requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
+    {
+      if (__has_val_) {
+        std::destroy_at(std::addressof(__union_.__v.__val_));
+      } else {
+        std::destroy_at(std::addressof(__union_.__v.__unex_));
+      }
     }
-  }
-
-private:
-  template <class, class>
-  friend class expected;
-
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_union_t<_Tp, _Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-};
-
-template <class _Tp, class _Err>
-struct __expected_base {
-protected:
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
-      : __repr_(std::forward<_Args>(__args)...) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
-    __repr_.__destroy_union();
-  }
-
-  template <class _Tag, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
-  {
-    __repr_.__construct_union(__tag, std::forward<_Args>(__args)...);
-  }
+    template <class _OtherUnion>
+    _LIBCPP_HIDE_FROM_ABI static constexpr __union_t __make_union(bool __has_val, _OtherUnion&& __other)
+      requires(!__can_stuff_tail())
+    {
+      if (__has_val)
+        return __union_t(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
+      else
+        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+    }
 
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_repr<_Tp, _Err, false> __repr_;
-};
+    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+        __can_stuff_tail(), __union_t>::__type __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+  };
 
-template <class _Tp, class _Err>
-    requires (sizeof(__expected_repr<_Tp, _Err, true>) == sizeof(__expected_union_t<_Tp, _Err>))
-struct __expected_base<_Tp, _Err> {
 protected:
   template <class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
@@ -350,32 +296,39 @@ struct __expected_base<_Tp, _Err> {
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other)
-      : __repr_(__make_repr(__has_val, std::forward<_OtherUnion>(__other))) {}
+    requires(__can_stuff_tail())
+      : __repr_(__expected_wrap_invoke_tag{},
+            [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
-    std::destroy_at(&__repr_);
+    if constexpr (__can_stuff_tail())
+      std::destroy_at(&__repr_.__v);
+    else
+      __repr_.__v.__destroy_union();
   }
 
   template <class _Tag, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
-  {
-    std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args) {
+    if constexpr (__can_stuff_tail())
+      std::construct_at(&__repr_.__v, __tag, std::forward<_Args>(__args)...);
+    else
+      __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...);
   }
 
 private:
-  using __repr = __expected_repr<_Tp, _Err, true>;
-
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
+    requires(__can_stuff_tail())
   {
     if (__has_val)
-      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_);
+      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
     else
-      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
   }
 
 protected:
-  __repr __repr_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+      !__can_stuff_tail(), __repr>::__type __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -424,7 +377,7 @@ class expected : private __expected_base<_Tp, _Err> {
     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
-      : __base(__other.__repr_.__has_val_, __other.__repr_.__union_) { }
+      : __base(__other.__repr_.__v.__has_val_, __other.__repr_.__v.__union_.__v) { }
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
@@ -435,7 +388,7 @@ class expected : private __expected_base<_Tp, _Err> {
     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
-      : __base(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) { }
+      : __base(__other.__repr_.__v.__has_val_, std::move(__other.__repr_.__v.__union_.__v)) { }
 
 private:
   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
@@ -475,14 +428,14 @@ class expected : private __expected_base<_Tp, _Err> {
   expected(const expected<_Up, _OtherErr>& __other)
     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __base(__other.__repr_.__has_val_, __other.__repr_.__union_) {}
+      : __base(__other.__repr_.__v.__has_val_, __other.__repr_.__v.__union_.__v) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __other)
     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __base(__other.__repr_.__has_val_, std::move(__other.__repr_.__union_)) {}
+      : __base(__other.__repr_.__v.__has_val_, std::move(__other.__repr_.__v.__union_.__v)) {}
 
   template <class _Up = _Tp>
     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
@@ -575,16 +528,16 @@ class expected : private __expected_base<_Tp, _Err> {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
-      this->__repr_.__union_.__val_ = __rhs.__repr_.__union_.__val_;
-    } else if (this->__repr_.__has_val_) {
+    if (this->__repr_.__v.__has_val_ && __rhs.__repr_.__v.__has_val_) {
+      this->__repr_.__v.__union_.__v.__val_.__v = __rhs.__repr_.__v.__union_.__v.__val_.__v;
+    } else if (this->__repr_.__v.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__union_.__val_, __rhs.__repr_.__union_.__unex_);
-    } else if (__rhs.__repr_.__has_val_) {
+          this->__repr_.__v.__union_.__v.__val_.__v, __rhs.__repr_.__v.__union_.__v.__unex_.__v);
+    } else if (__rhs.__repr_.__v.__has_val_) {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__val_);
+          this->__repr_.__v.__union_.__v.__unex_.__v, __rhs.__repr_.__v.__union_.__v.__val_.__v);
     } else {
-      this->__repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
+      this->__repr_.__v.__union_.__v.__unex_.__v = __rhs.__repr_.__v.__union_.__v.__unex_.__v;
     }
     return *this;
   }
@@ -601,16 +554,16 @@ class expected : private __expected_base<_Tp, _Err> {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__has_val_ && __rhs.__repr_.__has_val_) {
-      this->__repr_.__union_.__val_ = std::move(__rhs.__repr_.__union_.__val_);
-    } else if (this->__repr_.__has_val_) {
+    if (this->__repr_.__v.__has_val_ && __rhs.__repr_.__v.__has_val_) {
+      this->__repr_.__v.__union_.__v.__val_.__v = std::move(__rhs.__repr_.__v.__union_.__v.__val_.__v);
+    } else if (this->__repr_.__v.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__union_.__val_, std::move(__rhs.__repr_.__union_.__unex_));
-    } else if (__rhs.__repr_.__has_val_) {
+          this->__repr_.__v.__union_.__v.__val_.__v, std::move(__rhs.__repr_.__v.__union_.__v.__unex_.__v));
+    } else if (__rhs.__repr_.__v.__has_val_) {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__union_.__unex_, std::move(__rhs.__repr_.__union_.__val_));
+          this->__repr_.__v.__union_.__v.__unex_.__v, std::move(__rhs.__repr_.__v.__union_.__v.__val_.__v));
     } else {
-      this->__repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
+      this->__repr_.__v.__union_.__v.__unex_.__v = std::move(__rhs.__repr_.__v.__union_.__v.__unex_.__v);
     }
     return *this;
   }
@@ -625,11 +578,11 @@ class expected : private __expected_base<_Tp, _Err> {
               is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__has_val_) {
-      this->__repr_.__union_.__val_ = std::forward<_Up>(__v);
+    if (this->__repr_.__v.__has_val_) {
+      this->__repr_.__v.__union_.__v.__val_.__v = std::forward<_Up>(__v);
     } else {
       __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__union_.__unex_, std::forward<_Up>(__v));
+          this->__repr_.__v.__union_.__v.__unex_.__v, std::forward<_Up>(__v));
     }
     return *this;
   }
@@ -648,11 +601,11 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (this->__repr_.__has_val_) {
+    if (this->__repr_.__v.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__union_.__val_, __un.error());
+          this->__repr_.__v.__union_.__v.__val_.__v, __un.error());
     } else {
-      this->__repr_.__union_.__unex_ = __un.error();
+      this->__repr_.__v.__union_.__v.__unex_.__v = __un.error();
     }
     return *this;
   }
@@ -660,11 +613,11 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (this->__repr_.__has_val_) {
+    if (this->__repr_.__v.__has_val_) {
       __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__union_.__val_, std::move(__un.error()));
+          this->__repr_.__v.__union_.__v.__val_.__v, std::move(__un.error()));
     } else {
-      this->__repr_.__union_.__unex_ = std::move(__un.error());
+      this->__repr_.__v.__union_.__v.__unex_.__v = std::move(__un.error());
     }
     return *this;
   }
@@ -674,7 +627,7 @@ class expected : private __expected_base<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
     this->__destroy();
     this->__construct(in_place, std::forward<_Args>(__args)...);
-    return __repr_.__union_.__val_;
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
   template <class _Up, class... _Args>
@@ -682,7 +635,7 @@ class expected : private __expected_base<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
     this->__destroy();
     this->__construct(in_place, __il, std::forward<_Args>(__args)...);
-    return __repr_.__union_.__val_;
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
 public:
@@ -701,12 +654,12 @@ class expected : private __expected_base<_Tp, _Err> {
   {
     auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       if constexpr (is_nothrow_move_constructible_v<_Err>) {
-        _Err __tmp(std::move(__with_err.__repr_.__union_.__unex_));
+        _Err __tmp(std::move(__with_err.__repr_.__v.__union_.__v.__unex_.__v));
         __with_err.__destroy();
         auto __trans = std::__make_exception_guard([&] {
           __with_err.__construct(unexpect, std::move(__tmp));
         });
-        __with_err.__construct(in_place, std::move(__with_val.__repr_.__union_.__val_));
+        __with_err.__construct(in_place, std::move(__with_val.__repr_.__v.__union_.__v.__val_.__v));
         __trans.__complete();
         __with_val.__destroy();
         __with_val.__construct(unexpect, std::move(__tmp));
@@ -714,31 +667,31 @@ class expected : private __expected_base<_Tp, _Err> {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
-        _Tp __tmp(std::move(__with_val.__repr_.__union_.__val_));
+        _Tp __tmp(std::move(__with_val.__repr_.__v.__union_.__v.__val_.__v));
         __with_val.__destroy();
         auto __trans = std::__make_exception_guard([&] {
           __with_val.__construct(in_place, std::move(__tmp));
         });
-        __with_val.__construct(unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+        __with_val.__construct(unexpect, std::move(__with_err.__repr_.__v.__union_.__v.__unex_.__v));
         __trans.__complete();
         __with_err.__destroy();
         __with_err.__construct(in_place, std::move(__tmp));
       }
     };
 
-    if (this->__repr_.__has_val_) {
-      if (__rhs.__repr_.__has_val_) {
+    if (this->__repr_.__v.__has_val_) {
+      if (__rhs.__repr_.__v.__has_val_) {
         using std::swap;
-        swap(this->__repr_.__union_.__val_, __rhs.__repr_.__union_.__val_);
+        swap(this->__repr_.__v.__union_.__v.__val_.__v, __rhs.__repr_.__v.__union_.__v.__val_.__v);
       } else {
         __swap_val_unex_impl(*this, __rhs);
       }
     } else {
-      if (__rhs.__repr_.__has_val_) {
+      if (__rhs.__repr_.__v.__has_val_) {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
+        swap(this->__repr_.__v.__union_.__v.__unex_.__v, __rhs.__repr_.__v.__union_.__v.__unex_.__v);
       }
     }
   }
@@ -752,105 +705,105 @@ class expected : private __expected_base<_Tp, _Err> {
 
   // [expected.object.obs], observers
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(this->__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(this->__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return this->__repr_.__union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return this->__repr_.__union_.__val_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(this->__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(this->__repr_.__union_.__val_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
+    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__v.__has_val_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__v.__has_val_; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!this->__repr_.__has_val_) {
+    if (!this->__repr_.__v.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return this->__repr_.__union_.__val_;
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!this->__repr_.__has_val_) {
+    if (!this->__repr_.__v.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return this->__repr_.__union_.__val_;
+    return this->__repr_.__v.__union_.__v.__val_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!this->__repr_.__has_val_) {
+    if (!this->__repr_.__v.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(this->__repr_.__union_.__val_);
+    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!this->__repr_.__has_val_) {
+    if (!this->__repr_.__v.__has_val_) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(this->__repr_.__union_.__val_);
+    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__v.__union_.__v.__unex_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
+    return this->__repr_.__v.__union_.__v.__unex_.__v;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__v.__union_.__v.__unex_.__v);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
+    return std::move(this->__repr_.__v.__union_.__v.__unex_.__v);
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return this->__repr_.__has_val_ ? this->__repr_.__union_.__val_ : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__repr_.__v.__has_val_ ? this->__repr_.__v.__union_.__v.__val_.__v : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return this->__repr_.__has_val_ ? std::move(this->__repr_.__union_.__val_) : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__repr_.__v.__has_val_ ? std::move(this->__repr_.__v.__union_.__v.__val_.__v) : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up = _Err>
@@ -880,7 +833,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return _Up(unexpect, error());
   }
@@ -893,7 +846,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      return std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return _Up(unexpect, error());
   }
@@ -907,7 +860,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -921,7 +874,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -934,7 +887,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, this->__repr_.__union_.__val_);
+      return _Gp(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -947,7 +900,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, this->__repr_.__union_.__val_);
+      return _Gp(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -961,7 +914,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(this->__repr_.__union_.__val_));
+      return _Gp(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -975,7 +928,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(this->__repr_.__union_.__val_));
+      return _Gp(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -988,9 +941,10 @@ class expected : private __expected_base<_Tp, _Err> {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
+          std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
     } else {
-      std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
       return expected<_Up, _Err>();
     }
   }
@@ -1003,9 +957,10 @@ class expected : private __expected_base<_Tp, _Err> {
       return expected<_Up, _Err>(unexpect, error());
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
+          std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
     } else {
-      std::invoke(std::forward<_Func>(__f), this->__repr_.__union_.__val_);
+      std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
       return expected<_Up, _Err>();
     }
   }
@@ -1018,10 +973,10 @@ class expected : private __expected_base<_Tp, _Err> {
       return expected<_Up, _Err>(unexpect, std::move(error()));
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
+          std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
       return expected<_Up, _Err>();
     }
   }
@@ -1034,10 +989,10 @@ class expected : private __expected_base<_Tp, _Err> {
       return expected<_Up, _Err>(unexpect, std::move(error()));
     }
     if constexpr (!is_void_v<_Up>) {
-      return expected<_Up, _Err>(
-          __expected_construct_in_place_from_invoke_tag{}, std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
+          std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__union_.__val_));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
       return expected<_Up, _Err>();
     }
   }
@@ -1049,7 +1004,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, this->__repr_.__union_.__val_);
+      return expected<_Tp, _Gp>(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -1061,7 +1016,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, this->__repr_.__union_.__val_);
+      return expected<_Tp, _Gp>(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -1073,7 +1028,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -1086,7 +1041,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__union_.__val_));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -1096,25 +1051,25 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _T2, class _E2>
     requires(!is_void_v<_T2>)
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
-    if (__x.__repr_.__has_val_ != __y.__repr_.__has_val_) {
+    if (__x.__repr_.__v.__has_val_ != __y.__repr_.__v.__has_val_) {
       return false;
     } else {
-      if (__x.__repr_.__has_val_) {
-        return __x.__repr_.__union_.__val_ == __y.__repr_.__union_.__val_;
+      if (__x.__repr_.__v.__has_val_) {
+        return __x.__repr_.__v.__union_.__v.__val_.__v == __y.__repr_.__v.__union_.__v.__val_.__v;
       } else {
-        return __x.__repr_.__union_.__unex_ == __y.__repr_.__union_.__unex_;
+        return __x.__repr_.__v.__union_.__v.__unex_.__v == __y.__repr_.__v.__union_.__v.__unex_.__v;
       }
     }
   }
 
   template <class _T2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
-    return __x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__val_ == __v);
+    return __x.__repr_.__v.__has_val_ && static_cast<bool>(__x.__repr_.__v.__union_.__v.__val_.__v == __v);
   }
 
   template <class _E2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
-    return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __e.error());
+    return !__x.__repr_.__v.__has_val_ && static_cast<bool>(__x.__repr_.__v.__union_.__v.__unex_.__v == __e.error());
   }
 };
 
@@ -1137,7 +1092,7 @@ union __expected_void_union_t {
     requires(is_trivially_destructible_v<_ErrorType>)
   = default;
 
-  // __expected_repr's destructor handles this
+  // __repr's destructor handles this
   _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t() {}
 
   // XXX: Why are those not [[no_unique_address]]?
@@ -1170,7 +1125,7 @@ union __expected_void_union_t<_ErrorType> {
     requires(is_trivially_destructible_v<_ErrorType>)
   = default;
 
-  // __expected_repr's destructor handles this
+  // __repr's destructor handles this
   _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
     requires(!is_trivially_destructible_v<_ErrorType>)
   {}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index e316f7a0fc1b1e2..4d523d1ad69500e 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -38,11 +38,11 @@ struct BoolWithPadding {
 
 static_assert(sizeof(std::expected<Empty, Empty>) == sizeof(bool));
 static_assert(sizeof(std::expected<Empty, A>) == 2 * sizeof(int) + alignof(std::expected<Empty, A>));
-static_assert(sizeof(std::expected<Empty, B>) == sizeof(B) + alignof(std::expected<Empty, B>));
+static_assert(sizeof(std::expected<Empty, B>) == sizeof(B));
 static_assert(sizeof(std::expected<A, Empty>) == 2 * sizeof(int) + alignof(std::expected<A, Empty>));
 static_assert(sizeof(std::expected<A, A>) == 2 * sizeof(int) + alignof(std::expected<A, A>));
-static_assert(sizeof(std::expected<B, Empty>) == sizeof(B) + alignof(std::expected<B, Empty>));
-static_assert(sizeof(std::expected<B, B>) == sizeof(B) + alignof(std::expected<B, B>));
+static_assert(sizeof(std::expected<B, Empty>) == sizeof(B));
+static_assert(sizeof(std::expected<B, B>) == sizeof(B));
 
 // Check that `expected`'s datasize is large enough for the parameter type(s).
 static_assert(sizeof(std::expected<BoolWithPadding, Empty>) ==
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 16faddb280d3a33..965e82a7b403465 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -48,7 +48,6 @@ void test() {
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
-    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}

>From 540e76087c706a0c10dbbfb954e915b7615d2dfa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 25 Oct 2023 19:39:46 +0200
Subject: [PATCH 21/31] slight refactoring

---
 libcxx/include/__expected/expected.h | 85 +++++++++++++---------------
 1 file changed, 40 insertions(+), 45 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index a09a291de9ff9c1..2d660e67e7619c0 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -91,45 +91,42 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 template <class _Tp>
 concept __expected_union_member_no_unique_address = is_nothrow_move_constructible_v<_Tp>;
 
-struct __expected_wrap_invoke_tag {};
+struct __expected_invoke_tag {};
 
-template <class _Tp>
-struct __expected_wrap_unique {
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_unique(_Args&&... __args)
-      : __v(std::forward<_Args>(__args)...) {}
+template <bool _NoUnique, class _Tp>
+class __expected_conditional_no_unique_address {
+  struct __unique {
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __unique(_Args&&... __args)
+        : __v(std::forward<_Args>(__args)...) {}
 
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_unique(
-      __expected_wrap_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+    template <class _Func, class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __unique(
+        __expected_invoke_tag, _Func&& __f, _Args&&... __args)
+        : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-  _Tp __v;
-};
+    _Tp __v;
+  };
 
-template <class _Tp>
-struct __expected_wrap_no_unique {
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_no_unique(_Args&&... __args)
-      : __v(std::forward<_Args>(__args)...) {}
+  struct __no_unique {
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __no_unique(_Args&&... __args)
+        : __v(std::forward<_Args>(__args)...) {}
 
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_wrap_no_unique(
-      __expected_wrap_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+    template <class _Func, class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __no_unique(
+        __expected_invoke_tag, _Func&& __f, _Args&&... __args)
+        : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-  _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
-};
+    _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
+  };
 
-template <bool _NoUnique, class _Tp>
-struct __expected_conditional_no_unique_address {
-  using __type = std::conditional<_NoUnique,
-      __expected_wrap_no_unique<_Tp>, __expected_wrap_unique<_Tp>>::type;
+public:
+  using __type = std::conditional<_NoUnique, __no_unique, __unique>::type;
 };
 
 template <class _Tp, class _Err>
-struct __expected_base {
-private:
+class __expected_base {
   // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
   // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
   // it's not clear that it's implementable, given that the function is allowed to clobber
@@ -150,12 +147,12 @@ struct __expected_base {
     template <class _Func, class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
         std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __val_(__expected_wrap_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+        : __val_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
     template <class _Func, class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
         std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(__expected_wrap_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+        : __unex_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
@@ -204,7 +201,7 @@ struct __expected_base {
     template <class _OtherUnion>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
       requires(!__can_stuff_tail())
-        : __union_(__expected_wrap_invoke_tag{},
+        : __union_(__expected_invoke_tag{},
               [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
           __has_val_(__has_val) {}
 
@@ -289,6 +286,16 @@ struct __expected_base {
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
+  template <class _OtherUnion>
+  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
+    requires(__can_stuff_tail())
+  {
+    if (__has_val)
+      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
+    else
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+  }
+
 protected:
   template <class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(_Args&&... __args)
@@ -297,7 +304,7 @@ struct __expected_base {
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other)
     requires(__can_stuff_tail())
-      : __repr_(__expected_wrap_invoke_tag{},
+      : __repr_(__expected_invoke_tag{},
             [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
@@ -315,18 +322,6 @@ struct __expected_base {
       __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...);
   }
 
-private:
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
-    requires(__can_stuff_tail())
-  {
-    if (__has_val)
-      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
-    else
-      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
-  }
-
-protected:
   _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
       !__can_stuff_tail(), __repr>::__type __repr_;
 };

>From 8ef4fc0a329eb9d332f0c289a718cbd10071766f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 25 Oct 2023 20:10:11 +0200
Subject: [PATCH 22/31] more refactoring

---
 libcxx/include/__expected/expected.h | 45 +++++++++++++++-------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 2d660e67e7619c0..b4f3f3cfeef971f 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -125,6 +125,17 @@ class __expected_conditional_no_unique_address {
   using __type = std::conditional<_NoUnique, __no_unique, __unique>::type;
 };
 
+template <class _Union>
+_LIBCPP_HIDE_FROM_ABI constexpr bool __expected_can_stuff_tail()
+{
+  struct __x {
+  private:
+    _LIBCPP_NO_UNIQUE_ADDRESS _Union __union;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val;
+  };
+  return sizeof(__x) == sizeof(_Union);
+}
+
 template <class _Tp, class _Err>
 class __expected_base {
   // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
@@ -167,15 +178,7 @@ class __expected_base {
         __expected_union_member_no_unique_address<_Err>, _Err>::__type __unex_;
   };
 
-  _LIBCPP_HIDE_FROM_ABI static constexpr bool __can_stuff_tail()
-  {
-    struct __x {
-    private:
-      _LIBCPP_NO_UNIQUE_ADDRESS __union_t __union;
-      _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val;
-    };
-    return sizeof(__x) == sizeof(__union_t);
-  }
+  static constexpr bool __can_stuff_tail = __expected_can_stuff_tail<__union_t>();
 
   struct __repr {
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
@@ -200,7 +203,7 @@ class __expected_base {
 
     template <class _OtherUnion>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
-      requires(!__can_stuff_tail())
+      requires(!__can_stuff_tail)
         : __union_(__expected_invoke_tag{},
               [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
           __has_val_(__has_val) {}
@@ -229,13 +232,13 @@ class __expected_base {
     }
 
     _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-      requires(!__can_stuff_tail() && (is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>))
+      requires(!__can_stuff_tail && (is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>))
     {
       std::destroy_at(&__union_.__v);
     }
 
     _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-      requires(!__can_stuff_tail() && (!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>))
+      requires(!__can_stuff_tail && (!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>))
     {
       __destroy_union_member();
       std::destroy_at(&__union_.__v);
@@ -243,7 +246,7 @@ class __expected_base {
 
     template <class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t, _Args&&... __args)
-      requires(!__can_stuff_tail())
+      requires(!__can_stuff_tail)
     {
       std::construct_at(&__union_.__v, in_place, std::forward<_Args>(__args)...);
       __has_val_ = true;
@@ -251,7 +254,7 @@ class __expected_base {
 
     template <class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
-      requires(!__can_stuff_tail())
+      requires(!__can_stuff_tail)
     {
       std::construct_at(&__union_.__v, unexpect, std::forward<_Args>(__args)...);
       __has_val_ = false;
@@ -273,7 +276,7 @@ class __expected_base {
 
     template <class _OtherUnion>
     _LIBCPP_HIDE_FROM_ABI static constexpr __union_t __make_union(bool __has_val, _OtherUnion&& __other)
-      requires(!__can_stuff_tail())
+      requires(!__can_stuff_tail)
     {
       if (__has_val)
         return __union_t(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
@@ -282,13 +285,13 @@ class __expected_base {
     }
 
     _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __can_stuff_tail(), __union_t>::__type __union_;
+        __can_stuff_tail, __union_t>::__type __union_;
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
-    requires(__can_stuff_tail())
+    requires(__can_stuff_tail)
   {
     if (__has_val)
       return __repr(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
@@ -303,12 +306,12 @@ class __expected_base {
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other)
-    requires(__can_stuff_tail())
+    requires(__can_stuff_tail)
       : __repr_(__expected_invoke_tag{},
             [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
-    if constexpr (__can_stuff_tail())
+    if constexpr (__can_stuff_tail)
       std::destroy_at(&__repr_.__v);
     else
       __repr_.__v.__destroy_union();
@@ -316,14 +319,14 @@ class __expected_base {
 
   template <class _Tag, class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args) {
-    if constexpr (__can_stuff_tail())
+    if constexpr (__can_stuff_tail)
       std::construct_at(&__repr_.__v, __tag, std::forward<_Args>(__args)...);
     else
       __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...);
   }
 
   _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-      !__can_stuff_tail(), __repr>::__type __repr_;
+      !__can_stuff_tail, __repr>::__type __repr_;
 };
 
 template <class _Tp, class _Err>

>From a4a0ded79ace30db68abcdad81e9a0621ef18ea5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 25 Oct 2023 21:00:34 +0200
Subject: [PATCH 23/31] refactor expected<void>

---
 libcxx/include/__expected/expected.h          | 643 ++++++++----------
 .../no_unique_address.compile.pass.cpp        |   2 +-
 .../transform_error.mandates.verify.cpp       |   2 +-
 3 files changed, 287 insertions(+), 360 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index b4f3f3cfeef971f..e0f5489d2207a0e 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -262,7 +262,7 @@ class __expected_base {
 
   private:
     template <class, class>
-    friend class expected;
+    friend class __expected_base;
 
     _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
       requires(!is_trivially_destructible_v<_Tp> || !is_trivially_destructible_v<_Err>)
@@ -325,6 +325,15 @@ class __expected_base {
       __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...);
   }
 
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Tp& __val() { return __repr_.__v.__union_.__v.__val_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& __val() const { return __repr_.__v.__union_.__v.__val_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_.__v; }
+
+private:
   _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
       !__can_stuff_tail, __repr>::__type __repr_;
 };
@@ -375,7 +384,7 @@ class expected : private __expected_base<_Tp, _Err> {
     noexcept(is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
              !(is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>))
-      : __base(__other.__repr_.__v.__has_val_, __other.__repr_.__v.__union_.__v) { }
+      : __base(__other.__has_val(), __other.__union()) { }
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err>
@@ -386,7 +395,7 @@ class expected : private __expected_base<_Tp, _Err> {
     noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
              !(is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>))
-      : __base(__other.__repr_.__v.__has_val_, std::move(__other.__repr_.__v.__union_.__v)) { }
+      : __base(__other.__has_val(), std::move(__other.__union())) { }
 
 private:
   template <class _Up, class _OtherErr, class _UfQual, class _OtherErrQual>
@@ -426,14 +435,14 @@ class expected : private __expected_base<_Tp, _Err> {
   expected(const expected<_Up, _OtherErr>& __other)
     noexcept(is_nothrow_constructible_v<_Tp, const _Up&> &&
              is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __base(__other.__repr_.__v.__has_val_, __other.__repr_.__v.__union_.__v) {}
+      : __base(__other.__has_val(), __other.__union()) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _Up, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up, _Tp> || !is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __other)
     noexcept(is_nothrow_constructible_v<_Tp, _Up> && is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __base(__other.__repr_.__v.__has_val_, std::move(__other.__repr_.__v.__union_.__v)) {}
+      : __base(__other.__has_val(), std::move(__other.__union())) {}
 
   template <class _Up = _Tp>
     requires(!is_same_v<remove_cvref_t<_Up>, in_place_t> && !is_same_v<expected, remove_cvref_t<_Up>> &&
@@ -526,16 +535,14 @@ class expected : private __expected_base<_Tp, _Err> {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__v.__has_val_ && __rhs.__repr_.__v.__has_val_) {
-      this->__repr_.__v.__union_.__v.__val_.__v = __rhs.__repr_.__v.__union_.__v.__val_.__v;
-    } else if (this->__repr_.__v.__has_val_) {
-      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__v.__union_.__v.__val_.__v, __rhs.__repr_.__v.__union_.__v.__unex_.__v);
-    } else if (__rhs.__repr_.__v.__has_val_) {
-      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__v.__union_.__v.__unex_.__v, __rhs.__repr_.__v.__union_.__v.__val_.__v);
+    if (this->__has_val() && __rhs.__has_val()) {
+      this->__val() = __rhs.__val();
+    } else if (this->__has_val()) {
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), __rhs.__unex());
+    } else if (__rhs.__has_val()) {
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), __rhs.__val());
     } else {
-      this->__repr_.__v.__union_.__v.__unex_.__v = __rhs.__repr_.__v.__union_.__v.__unex_.__v;
+      this->__unex() = __rhs.__unex();
     }
     return *this;
   }
@@ -552,16 +559,14 @@ class expected : private __expected_base<_Tp, _Err> {
              (is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__v.__has_val_ && __rhs.__repr_.__v.__has_val_) {
-      this->__repr_.__v.__union_.__v.__val_.__v = std::move(__rhs.__repr_.__v.__union_.__v.__val_.__v);
-    } else if (this->__repr_.__v.__has_val_) {
-      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__v.__union_.__v.__val_.__v, std::move(__rhs.__repr_.__v.__union_.__v.__unex_.__v));
-    } else if (__rhs.__repr_.__v.__has_val_) {
-      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__v.__union_.__v.__unex_.__v, std::move(__rhs.__repr_.__v.__union_.__v.__val_.__v));
+    if (this->__has_val() && __rhs.__has_val()) {
+      this->__val() = std::move(__rhs.__val());
+    } else if (this->__has_val()) {
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), std::move(__rhs.__unex()));
+    } else if (__rhs.__has_val()) {
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), std::move(__rhs.__val()));
     } else {
-      this->__repr_.__v.__union_.__v.__unex_.__v = std::move(__rhs.__repr_.__v.__union_.__v.__unex_.__v);
+      this->__unex() = std::move(__rhs.__unex());
     }
     return *this;
   }
@@ -576,11 +581,10 @@ class expected : private __expected_base<_Tp, _Err> {
               is_nothrow_move_constructible_v<_Tp> ||
               is_nothrow_move_constructible_v<_Err>))
   {
-    if (this->__repr_.__v.__has_val_) {
-      this->__repr_.__v.__union_.__v.__val_.__v = std::forward<_Up>(__v);
+    if (this->__has_val()) {
+      this->__val() = std::forward<_Up>(__v);
     } else {
-      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(
-          this->__repr_.__v.__union_.__v.__unex_.__v, std::forward<_Up>(__v));
+      __reinit_expected<in_place_t, unexpect_t, _Tp, _Err>(this->__unex(), std::forward<_Up>(__v));
     }
     return *this;
   }
@@ -599,11 +603,10 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (this->__repr_.__v.__has_val_) {
-      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__v.__union_.__v.__val_.__v, __un.error());
+    if (this->__has_val()) {
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), __un.error());
     } else {
-      this->__repr_.__v.__union_.__v.__unex_.__v = __un.error();
+      this->__unex() = __un.error();
     }
     return *this;
   }
@@ -611,11 +614,10 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _OtherErr>
     requires(__can_assign_from_unexpected<_OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (this->__repr_.__v.__has_val_) {
-      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(
-          this->__repr_.__v.__union_.__v.__val_.__v, std::move(__un.error()));
+    if (this->__has_val()) {
+      __reinit_expected<unexpect_t, in_place_t, _Err, _Tp>(this->__val(), std::move(__un.error()));
     } else {
-      this->__repr_.__v.__union_.__v.__unex_.__v = std::move(__un.error());
+      this->__unex() = std::move(__un.error());
     }
     return *this;
   }
@@ -625,15 +627,15 @@ class expected : private __expected_base<_Tp, _Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(_Args&&... __args) noexcept {
     this->__destroy();
     this->__construct(in_place, std::forward<_Args>(__args)...);
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    return this->__val();
   }
 
   template <class _Up, class... _Args>
-    requires is_nothrow_constructible_v< _Tp, initializer_list<_Up>&, _Args... >
+    requires is_nothrow_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) noexcept {
     this->__destroy();
     this->__construct(in_place, __il, std::forward<_Args>(__args)...);
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    return this->__val();
   }
 
 public:
@@ -652,12 +654,12 @@ class expected : private __expected_base<_Tp, _Err> {
   {
     auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       if constexpr (is_nothrow_move_constructible_v<_Err>) {
-        _Err __tmp(std::move(__with_err.__repr_.__v.__union_.__v.__unex_.__v));
+        _Err __tmp(std::move(__with_err.__unex()));
         __with_err.__destroy();
         auto __trans = std::__make_exception_guard([&] {
           __with_err.__construct(unexpect, std::move(__tmp));
         });
-        __with_err.__construct(in_place, std::move(__with_val.__repr_.__v.__union_.__v.__val_.__v));
+        __with_err.__construct(in_place, std::move(__with_val.__val()));
         __trans.__complete();
         __with_val.__destroy();
         __with_val.__construct(unexpect, std::move(__tmp));
@@ -665,31 +667,31 @@ class expected : private __expected_base<_Tp, _Err> {
         static_assert(is_nothrow_move_constructible_v<_Tp>,
                       "To provide strong exception guarantee, Tp has to satisfy `is_nothrow_move_constructible_v` so "
                       "that it can be reverted to the previous state in case an exception is thrown during swap.");
-        _Tp __tmp(std::move(__with_val.__repr_.__v.__union_.__v.__val_.__v));
+        _Tp __tmp(std::move(__with_val.__val()));
         __with_val.__destroy();
         auto __trans = std::__make_exception_guard([&] {
           __with_val.__construct(in_place, std::move(__tmp));
         });
-        __with_val.__construct(unexpect, std::move(__with_err.__repr_.__v.__union_.__v.__unex_.__v));
+        __with_val.__construct(unexpect, std::move(__with_err.__unex()));
         __trans.__complete();
         __with_err.__destroy();
         __with_err.__construct(in_place, std::move(__tmp));
       }
     };
 
-    if (this->__repr_.__v.__has_val_) {
-      if (__rhs.__repr_.__v.__has_val_) {
+    if (this->__has_val()) {
+      if (__rhs.__has_val()) {
         using std::swap;
-        swap(this->__repr_.__v.__union_.__v.__val_.__v, __rhs.__repr_.__v.__union_.__v.__val_.__v);
+        swap(this->__val(), __rhs.__val());
       } else {
         __swap_val_unex_impl(*this, __rhs);
       }
     } else {
-      if (__rhs.__repr_.__v.__has_val_) {
+      if (__rhs.__has_val()) {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(this->__repr_.__v.__union_.__v.__unex_.__v, __rhs.__repr_.__v.__union_.__v.__unex_.__v);
+        swap(this->__unex(), __rhs.__unex());
       }
     }
   }
@@ -703,105 +705,105 @@ class expected : private __expected_base<_Tp, _Err> {
 
   // [expected.object.obs], observers
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp* operator->() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(this->__repr_.__v.__union_.__v.__val_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__val());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp* operator->() noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator-> requires the expected to contain a value");
-    return std::addressof(this->__repr_.__v.__union_.__v.__val_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator-> requires the expected to contain a value");
+    return std::addressof(this->__val());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator* requires the expected to contain a value");
+    return this->__val();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator* requires the expected to contain a value");
+    return this->__val();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator* requires the expected to contain a value");
+    return std::move(this->__val());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__v.__has_val_, "expected::operator* requires the expected to contain a value");
-    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator* requires the expected to contain a value");
+    return std::move(this->__val());
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__v.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__v.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!this->__repr_.__v.__has_val_) {
+    if (!this->__has_val()) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    return this->__val();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
     static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible");
-    if (!this->__repr_.__v.__has_val_) {
+    if (!this->__has_val()) {
       std::__throw_bad_expected_access<_Err>(std::as_const(error()));
     }
-    return this->__repr_.__v.__union_.__v.__val_.__v;
+    return this->__val();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!this->__repr_.__v.__has_val_) {
+    if (!this->__has_val()) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
+    return std::move(this->__val());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
     static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>,
                   "error_type has to be both copy constructible and constructible from decltype(std::move(error()))");
-    if (!this->__repr_.__v.__has_val_) {
+    if (!this->__has_val()) {
       std::__throw_bad_expected_access<_Err>(std::move(error()));
     }
-    return std::move(this->__repr_.__v.__union_.__v.__val_.__v);
+    return std::move(this->__val());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__v.__union_.__v.__unex_.__v;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return this->__unex();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__v.__union_.__v.__unex_.__v;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return this->__unex();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__v.__union_.__v.__unex_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return std::move(this->__unex());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__v.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__v.__union_.__v.__unex_.__v);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return std::move(this->__unex());
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return this->__repr_.__v.__has_val_ ? this->__repr_.__v.__union_.__v.__val_.__v : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__has_val() ? this->__val() : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up>
   _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible");
     static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type");
-    return this->__repr_.__v.__has_val_ ? std::move(this->__repr_.__v.__union_.__v.__val_.__v) : static_cast<_Tp>(std::forward<_Up>(__v));
+    return this->__has_val() ? std::move(this->__val()) : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
   template <class _Up = _Err>
@@ -831,7 +833,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+      return std::invoke(std::forward<_Func>(__f), this->__val());
     }
     return _Up(unexpect, error());
   }
@@ -844,7 +846,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(**this) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+      return std::invoke(std::forward<_Func>(__f), this->__val());
     }
     return _Up(unexpect, error());
   }
@@ -858,7 +860,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -872,7 +874,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Up::error_type, _Err>,
                   "The result of f(std::move(**this)) must have the same error_type as this expected");
     if (has_value()) {
-      return std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
     }
     return _Up(unexpect, std::move(error()));
   }
@@ -885,7 +887,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
+      return _Gp(in_place, this->__val());
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -898,7 +900,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(error()) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
+      return _Gp(in_place, this->__val());
     }
     return std::invoke(std::forward<_Func>(__f), error());
   }
@@ -912,7 +914,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return _Gp(in_place, std::move(this->__val()));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -926,7 +928,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(is_same_v<typename _Gp::value_type, _Tp>,
                   "The result of f(std::move(error())) must have the same value_type as this expected");
     if (has_value()) {
-      return _Gp(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return _Gp(in_place, std::move(this->__val()));
     }
     return std::invoke(std::forward<_Func>(__f), std::move(error()));
   }
@@ -940,9 +942,9 @@ class expected : private __expected_base<_Tp, _Err> {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
-          std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+          std::forward<_Func>(__f), this->__val());
     } else {
-      std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+      std::invoke(std::forward<_Func>(__f), this->__val());
       return expected<_Up, _Err>();
     }
   }
@@ -956,9 +958,9 @@ class expected : private __expected_base<_Tp, _Err> {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
-          std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+          std::forward<_Func>(__f), this->__val());
     } else {
-      std::invoke(std::forward<_Func>(__f), this->__repr_.__v.__union_.__v.__val_.__v);
+      std::invoke(std::forward<_Func>(__f), this->__val());
       return expected<_Up, _Err>();
     }
   }
@@ -972,9 +974,9 @@ class expected : private __expected_base<_Tp, _Err> {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
-          std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+          std::forward<_Func>(__f), std::move(this->__val()));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
       return expected<_Up, _Err>();
     }
   }
@@ -988,9 +990,9 @@ class expected : private __expected_base<_Tp, _Err> {
     }
     if constexpr (!is_void_v<_Up>) {
       return expected<_Up, _Err>(__expected_construct_in_place_from_invoke_tag{},
-          std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+          std::forward<_Func>(__f), std::move(this->__val()));
     } else {
-      std::invoke(std::forward<_Func>(__f), std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
       return expected<_Up, _Err>();
     }
   }
@@ -1002,7 +1004,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
+      return expected<_Tp, _Gp>(in_place, this->__val());
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -1014,7 +1016,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(error()) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, this->__repr_.__v.__union_.__v.__val_.__v);
+      return expected<_Tp, _Gp>(in_place, this->__val());
     }
     return expected<_Tp, _Gp>(__expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), error());
   }
@@ -1026,7 +1028,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__val()));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -1039,7 +1041,7 @@ class expected : private __expected_base<_Tp, _Err> {
     static_assert(__valid_std_unexpected<_Gp>::value,
                   "The result of f(std::move(error())) must be a valid template argument for unexpected");
     if (has_value()) {
-      return expected<_Tp, _Gp>(in_place, std::move(this->__repr_.__v.__union_.__v.__val_.__v));
+      return expected<_Tp, _Gp>(in_place, std::move(this->__val()));
     }
     return expected<_Tp, _Gp>(
         __expected_construct_unexpected_from_invoke_tag{}, std::forward<_Func>(__f), std::move(error()));
@@ -1049,252 +1051,175 @@ class expected : private __expected_base<_Tp, _Err> {
   template <class _T2, class _E2>
     requires(!is_void_v<_T2>)
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
-    if (__x.__repr_.__v.__has_val_ != __y.__repr_.__v.__has_val_) {
+    if (__x.__has_val() != __y.__has_val()) {
       return false;
     } else {
-      if (__x.__repr_.__v.__has_val_) {
-        return __x.__repr_.__v.__union_.__v.__val_.__v == __y.__repr_.__v.__union_.__v.__val_.__v;
+      if (__x.__has_val()) {
+        return __x.__val() == __y.__val();
       } else {
-        return __x.__repr_.__v.__union_.__v.__unex_.__v == __y.__repr_.__v.__union_.__v.__unex_.__v;
+        return __x.__unex() == __y.__unex();
       }
     }
   }
 
   template <class _T2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
-    return __x.__repr_.__v.__has_val_ && static_cast<bool>(__x.__repr_.__v.__union_.__v.__val_.__v == __v);
+    return __x.__has_val() && static_cast<bool>(__x.__val() == __v);
   }
 
   template <class _E2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
-    return !__x.__repr_.__v.__has_val_ && static_cast<bool>(__x.__repr_.__v.__union_.__v.__unex_.__v == __e.error());
+    return !__x.__has_val() && static_cast<bool>(__x.__unex() == __e.error());
   }
 };
 
-struct __expected_empty_t {};
-
-template <class _ErrorType>
-union __expected_void_union_t {
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(in_place_t) : __empty_() {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(unexpect_t, _Args&&... __args)
-      : __unex_(std::forward<_Args>(__args)...) {}
-
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(
-      __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
-    requires(is_trivially_destructible_v<_ErrorType>)
-  = default;
-
-  // __repr's destructor handles this
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t() {}
+template <class _Err>
+class __expected_void_base {
+  struct __empty_t {};
+  // use named union because [[no_unique_address]] cannot be applied to an unnamed union,
+  // also guaranteed elision into a potentially-overlapping subobject is unsettled (and
+  // it's not clear that it's implementable, given that the function is allowed to clobber
+  // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
+  union __union_t {
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete;
 
-  // XXX: Why are those not [[no_unique_address]]?
-  __expected_empty_t __empty_;
-  _ErrorType __unex_;
-};
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t) : __empty_() {}
 
-// use named union because [[no_unique_address]] cannot be applied to an unnamed union,
-// also guaranteed elision into a potentially-overlapping subobject is unsettled (and
-// it's not clear that it's implementable, given that the function is allowed to clobber
-// the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
-template <class _ErrorType>
-  requires is_trivially_move_constructible_v<_ErrorType>
-union __expected_void_union_t<_ErrorType> {
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_union_t(const __expected_void_union_t&) = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_union_t& operator=(const __expected_void_union_t&) = default;
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(unexpect_t, _Args&&... __args)
+        : __unex_(std::forward<_Args>(__args)...) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(in_place_t) : __empty_() {}
+    template <class _Func, class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
+        __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
+        : __unex_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
 
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(unexpect_t, _Args&&... __args)
-      : __unex_(std::forward<_Args>(__args)...) {}
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+      requires(is_trivially_destructible_v<_Err>)
+    = default;
 
-  template <class _Func, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_union_t(
-      __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-      : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+    // __repr's destructor handles this
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
+      requires(!is_trivially_destructible_v<_Err>)
+    {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
-    requires(is_trivially_destructible_v<_ErrorType>)
-  = default;
+    _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+        __expected_union_member_no_unique_address<_Err>, _Err>::__type __unex_;
+  };
 
-  // __repr's destructor handles this
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_union_t()
-    requires(!is_trivially_destructible_v<_ErrorType>)
-  {}
+  static constexpr bool __can_stuff_tail = __expected_can_stuff_tail<__union_t>();
 
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_empty_t __empty_;
-  _LIBCPP_NO_UNIQUE_ADDRESS _ErrorType __unex_;
-};
+  struct __repr {
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr() = delete;
 
-template <class _Err, bool _StuffTail = false>
-struct __expected_void_repr {
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr() = delete;
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(in_place_t __tag)
+        : __union_(__tag), __has_val_(true) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(in_place_t __tag)
-      : __union_(__tag), __has_val_(true) {}
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(unexpect_t __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(unexpect_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(
+        std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
+        : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
 
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(
-      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
+    template <class _OtherUnion>
+    _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
+      requires(!__can_stuff_tail)
+        : __union_(__expected_invoke_tag{},
+              [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
+          __has_val_(__has_val) {}
 
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(bool __has_val, _OtherUnion&& __other)
-      : __union_(__make_union(__has_val, std::forward<_OtherUnion>(__other))), __has_val_(__has_val) {}
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(const __repr&)
+      requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr(__repr&&)
+      requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
+    = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
-    requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
-  = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&)
-    requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
-  = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr& operator=(const __expected_void_repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
+      requires(is_trivially_destructible_v<_Err>)
+    = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
-    requires(is_trivially_destructible_v<_Err>)
-  = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
+      requires(!is_trivially_destructible_v<_Err>)
+    {
+      __destroy_union_member();
+    }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
-    requires(!is_trivially_destructible_v<_Err>)
-  {
-    __destroy_union_member();
-  }
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+      requires(!__can_stuff_tail && is_trivially_destructible_v<_Err>)
+    {
+      std::destroy_at(&__union_.__v);
+    }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-    requires(is_trivially_destructible_v<_Err>)
-  {
-    std::destroy_at(&__union_);
-  }
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
+      requires(!__can_stuff_tail && !is_trivially_destructible_v<_Err>)
+    {
+      __destroy_union_member();
+      std::destroy_at(&__union_.__v);
+    }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union()
-    requires(!is_trivially_destructible_v<_Err>)
-  {
-    __destroy_union_member();
-    std::destroy_at(&__union_);
-  }
+    _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t)
+      requires(!__can_stuff_tail)
+    {
+      std::construct_at(&__union_.__v, in_place);
+      __has_val_ = true;
+    }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(in_place_t)
-  {
-    std::construct_at(&__union_, in_place);
-    __has_val_ = true;
-  }
+    template <class... _Args>
+    _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
+      requires(!__can_stuff_tail)
+    {
+      std::construct_at(&__union_.__v, unexpect, std::forward<_Args>(__args)...);
+      __has_val_ = false;
+    }
 
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct_union(unexpect_t, _Args&&... __args)
-  {
-    std::construct_at(&__union_, unexpect, std::forward<_Args>(__args)...);
-    __has_val_ = false;
-  }
+  private:
+    template <class>
+    friend class __expected_void_base;
 
-private:
-  template <class, class>
-  friend class expected;
+    _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
+      requires(!is_trivially_destructible_v<_Err>)
+    {
+      if (!__has_val_)
+        std::destroy_at(std::addressof(__union_.__v.__unex_));
+    }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy_union_member()
-    requires(!is_trivially_destructible_v<_Err>)
-  {
-    if (!__has_val_) {
-      std::destroy_at(std::addressof(__union_.__unex_));
+    template <class _OtherUnion>
+    _LIBCPP_HIDE_FROM_ABI static constexpr __union_t __make_union(bool __has_val, _OtherUnion&& __other)
+      requires(!__can_stuff_tail)
+    {
+      if (__has_val)
+        return __union_t(in_place);
+      else
+        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
     }
-  }
+
+    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+        __can_stuff_tail, __union_t>::__type __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
+  };
 
   template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI static constexpr __expected_void_union_t<_Err>
-  __make_union(bool __has_val, _OtherUnion&& __other)
+  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
+    requires(__can_stuff_tail)
   {
     if (__has_val)
-      return __expected_void_union_t<_Err>(in_place);
+      return __repr(in_place);
     else
-      return __expected_void_union_t<_Err>(unexpect, std::forward<_OtherUnion>(__other).__unex_);
-  }
-
-  __expected_void_union_t<_Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-};
-
-template <class _Err>
-struct __expected_void_repr<_Err, true> {
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr() = delete;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(in_place_t __tag)
-      : __union_(__tag), __has_val_(true) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(unexpect_t __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_repr(
-      std::__expected_construct_unexpected_from_invoke_tag __tag, _Args&&... __args)
-      : __union_(__tag, std::forward<_Args>(__args)...), __has_val_(false) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(const __expected_void_repr&)
-    requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
-  = default;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&) = delete;
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr(__expected_void_repr&&)
-    requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __expected_void_repr& operator=(const __expected_void_repr&) = delete;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
-    requires(is_trivially_destructible_v<_Err>)
-  = default;
-
-  _LIBCPP_HIDE_FROM_ABI constexpr ~__expected_void_repr()
-    requires(!is_trivially_destructible_v<_Err>)
-  {
-    if (!__has_val_) {
-      std::destroy_at(std::addressof(__union_.__unex_));
-    }
-  }
-
-private:
-  template <class, class>
-  friend class expected;
-
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_void_union_t<_Err> __union_;
-  _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
-};
-
-template <class _Err>
-struct __expected_void_base {
-protected:
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args)
-      : __repr_(std::forward<_Args>(__args)...) {}
-
-  _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
-    __repr_.__destroy_union();
-  }
-
-  template <class _Tag, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
-  {
-    __repr_.__construct_union(__tag, std::forward<_Args>(__args)...);
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
   }
 
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_void_repr<_Err, false> __repr_;
-};
-
-template <class _Err>
-    requires (sizeof(__expected_void_repr<_Err, true>) == sizeof(__expected_void_union_t<_Err>))
-struct __expected_void_base<_Err> {
 protected:
   template <class... _Args>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(_Args&&... __args)
@@ -1302,32 +1227,34 @@ struct __expected_void_base<_Err> {
 
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(bool __has_val, _OtherUnion&& __other)
-      : __repr_(__make_repr(__has_val, std::forward<_OtherUnion>(__other))) {}
+    requires(__can_stuff_tail)
+      : __repr_(__expected_invoke_tag{},
+            [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
-    std::destroy_at(&__repr_);
+    if constexpr (__can_stuff_tail)
+      std::destroy_at(&__repr_.__v);
+    else
+      __repr_.__v.__destroy_union();
   }
 
   template <class _Tag, class... _Args>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args)
-  {
-    std::construct_at(&__repr_, __tag, std::forward<_Args>(__args)...);
-  }
-
-private:
-  using __repr = __expected_void_repr<_Err, true>;
-
-  template <class _OtherUnion>
-  _LIBCPP_HIDE_FROM_ABI static constexpr __repr __make_repr(bool __has_val, _OtherUnion&& __other)
-  {
-    if (__has_val)
-      return __repr(in_place);
+  _LIBCPP_HIDE_FROM_ABI constexpr void __construct(_Tag __tag, _Args&&... __args) {
+    if constexpr (__can_stuff_tail)
+      std::construct_at(&__repr_.__v, __tag, std::forward<_Args>(__args)...);
     else
-      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
+      __repr_.__v.__construct_union(__tag, std::forward<_Args>(__args)...);
   }
 
-protected:
-  __repr __repr_;
+  _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_.__v; }
+
+private:
+  _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
+      !__can_stuff_tail, __repr>::__type __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -1371,7 +1298,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(const expected& __rhs)
     noexcept(is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_constructible_v<_Err> && !is_trivially_copy_constructible_v<_Err>)
-      : __base(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
+      : __base(__rhs.__has_val(), __rhs.__union()) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&&)
     requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
@@ -1380,21 +1307,21 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   _LIBCPP_HIDE_FROM_ABI constexpr expected(expected&& __rhs)
     noexcept(is_nothrow_move_constructible_v<_Err>)
     requires(is_move_constructible_v<_Err> && !is_trivially_move_constructible_v<_Err>)
-      : __base(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
+      : __base(__rhs.__has_val(), std::move(__rhs.__union())) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, const _OtherErr&>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<const _OtherErr&, _Err>)
   expected(const expected<_Up, _OtherErr>& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, const _OtherErr&>) // strengthened
-      : __base(__rhs.__repr_.__has_val_, __rhs.__repr_.__union_) {}
+      : __base(__rhs.__has_val(), __rhs.__union()) {}
 
   template <class _Up, class _OtherErr>
     requires __can_convert<_Up, _OtherErr, _OtherErr>::value
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherErr, _Err>)
   expected(expected<_Up, _OtherErr>&& __rhs)
     noexcept(is_nothrow_constructible_v<_Err, _OtherErr>) // strengthened
-      : __base(__rhs.__repr_.__has_val_, std::move(__rhs.__repr_.__union_)) {}
+      : __base(__rhs.__has_val(), std::move(__rhs.__union())) {}
 
   template <class _OtherErr>
     requires is_constructible_v<_Err, const _OtherErr&>
@@ -1459,15 +1386,15 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
     noexcept(is_nothrow_copy_assignable_v<_Err> && is_nothrow_copy_constructible_v<_Err>) // strengthened
     requires(is_copy_assignable_v<_Err> && is_copy_constructible_v<_Err>)
   {
-    if (this->__repr_.__has_val_) {
-      if (!__rhs.__repr_.__has_val_) {
-        __reinit_expected(unexpect, __rhs.__repr_.__union_.__unex_);
+    if (this->__has_val()) {
+      if (!__rhs.__has_val()) {
+        __reinit_expected(unexpect, __rhs.__unex());
       }
     } else {
-      if (__rhs.__repr_.__has_val_) {
+      if (__rhs.__has_val()) {
         __reinit_expected(in_place);
       } else {
-        this->__repr_.__union_.__unex_ = __rhs.__repr_.__union_.__unex_;
+        this->__unex() = __rhs.__unex();
       }
     }
     return *this;
@@ -1481,15 +1408,15 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
     requires(is_move_assignable_v<_Err> &&
              is_move_constructible_v<_Err>)
   {
-    if (this->__repr_.__has_val_) {
-      if (!__rhs.__repr_.__has_val_) {
-        __reinit_expected(unexpect, std::move(__rhs.__repr_.__union_.__unex_));
+    if (this->__has_val()) {
+      if (!__rhs.__has_val()) {
+        __reinit_expected(unexpect, std::move(__rhs.__unex()));
       }
     } else {
-      if (__rhs.__repr_.__has_val_) {
+      if (__rhs.__has_val()) {
         __reinit_expected(in_place);
       } else {
-        this->__repr_.__union_.__unex_ = std::move(__rhs.__repr_.__union_.__unex_);
+        this->__unex() = std::move(__rhs.__unex());
       }
     }
     return *this;
@@ -1498,10 +1425,10 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, const _OtherErr&> && is_assignable_v<_Err&, const _OtherErr&>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(const unexpected<_OtherErr>& __un) {
-    if (this->__repr_.__has_val_) {
+    if (this->__has_val()) {
       __reinit_expected(unexpect, __un.error());
     } else {
-      this->__repr_.__union_.__unex_ = __un.error();
+      this->__unex() = __un.error();
     }
     return *this;
   }
@@ -1509,16 +1436,16 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   template <class _OtherErr>
     requires(is_constructible_v<_Err, _OtherErr> && is_assignable_v<_Err&, _OtherErr>)
   _LIBCPP_HIDE_FROM_ABI constexpr expected& operator=(unexpected<_OtherErr>&& __un) {
-    if (this->__repr_.__has_val_) {
+    if (this->__has_val()) {
       __reinit_expected(unexpect, std::move(__un.error()));
     } else {
-      this->__repr_.__union_.__unex_ = std::move(__un.error());
+      this->__unex() = std::move(__un.error());
     }
     return *this;
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void emplace() noexcept {
-    if (!this->__repr_.__has_val_) {
+    if (!this->__has_val()) {
       __reinit_expected(in_place);
     }
   }
@@ -1530,21 +1457,21 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   {
     auto __swap_val_unex_impl = [](expected& __with_val, expected& __with_err) {
       // May throw, but will re-engage `__with_val` in that case.
-      __with_val.__reinit_expected(unexpect, std::move(__with_err.__repr_.__union_.__unex_));
+      __with_val.__reinit_expected(unexpect, std::move(__with_err.__unex()));
       // Will not throw.
       __with_err.__reinit_expected(in_place);
     };
 
-    if (this->__repr_.__has_val_) {
-      if (!__rhs.__repr_.__has_val_) {
+    if (this->__has_val()) {
+      if (!__rhs.__has_val()) {
         __swap_val_unex_impl(*this, __rhs);
       }
     } else {
-      if (__rhs.__repr_.__has_val_) {
+      if (__rhs.__has_val()) {
         __swap_val_unex_impl(__rhs, *this);
       } else {
         using std::swap;
-        swap(this->__repr_.__union_.__unex_, __rhs.__repr_.__union_.__unex_);
+        swap(this->__unex(), __rhs.__unex());
       }
     }
   }
@@ -1557,44 +1484,44 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   }
 
   // [expected.void.obs], observers
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__repr_.__has_val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__repr_.__has_val_, "expected::operator* requires the expected to contain a value");
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->__has_val(), "expected::operator* requires the expected to contain a value");
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() const& {
-    if (!this->__repr_.__has_val_) {
-      std::__throw_bad_expected_access<_Err>(this->__repr_.__union_.__unex_);
+    if (!this->__has_val()) {
+      std::__throw_bad_expected_access<_Err>(this->__unex());
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr void value() && {
-    if (!this->__repr_.__has_val_) {
-      std::__throw_bad_expected_access<_Err>(std::move(this->__repr_.__union_.__unex_));
+    if (!this->__has_val()) {
+      std::__throw_bad_expected_access<_Err>(std::move(this->__unex()));
     }
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return this->__unex();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return this->__repr_.__union_.__unex_;
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return this->__unex();
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return std::move(this->__unex());
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept {
-    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__repr_.__has_val_, "expected::error requires the expected to contain an error");
-    return std::move(this->__repr_.__union_.__unex_);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!this->__has_val(), "expected::error requires the expected to contain an error");
+    return std::move(this->__unex());
   }
 
   template <class _Up = _Err>
@@ -1830,16 +1757,16 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> {
   template <class _T2, class _E2>
     requires is_void_v<_T2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
-    if (__x.__repr_.__has_val_ != __y.__repr_.__has_val_) {
+    if (__x.__has_val() != __y.__has_val()) {
       return false;
     } else {
-      return __x.__repr_.__has_val_ || static_cast<bool>(__x.__repr_.__union_.__unex_ == __y.__repr_.__union_.__unex_);
+      return __x.__has_val() || static_cast<bool>(__x.__unex() == __y.__unex());
     }
   }
 
   template <class _E2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
-    return !__x.__repr_.__has_val_ && static_cast<bool>(__x.__repr_.__union_.__unex_ == __y.error());
+    return !__x.__has_val() && static_cast<bool>(__x.__unex() == __y.error());
   }
 };
 
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index e764dbd66acaa9a..eab2acf1471842e 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -38,7 +38,7 @@ struct BoolWithPadding {
 
 static_assert(sizeof(std::expected<void, Empty>) == sizeof(bool));
 static_assert(sizeof(std::expected<void, A>) == 2 * sizeof(int) + alignof(std::expected<void, A>));
-static_assert(sizeof(std::expected<void, B>) == sizeof(B) + alignof(std::expected<void, B>));
+static_assert(sizeof(std::expected<void, B>) == sizeof(B));
 
 // Check that `expected`'s datasize is large enough for the parameter type(s).
 static_assert(sizeof(std::expected<void, BoolWithPadding>) ==
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 7687a42cb1a8655..9c8cbcdaaa6d63b 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -48,12 +48,12 @@ void test() {
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
-    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
     // expected-error-re@*:* {{call to deleted constructor of {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
+    // expected-error-re@*:* {{call to deleted constructor of {{.*}}}}
   }
 
   // Test const& overload

>From 0d100bf50afe0a4ceabba1192a46f542da221c66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Wed, 25 Oct 2023 21:11:27 +0200
Subject: [PATCH 24/31] add missing __repr and __union_t operators to be more
 explicit

---
 libcxx/include/__expected/expected.h | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index e0f5489d2207a0e..529965f60c2cbe9 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -143,9 +143,18 @@ class __expected_base {
   // it's not clear that it's implementable, given that the function is allowed to clobber
   // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
   union __union_t {
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&)
+      requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err> &&
+               is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&)
+      requires(is_move_constructible_v<_Tp> && is_move_constructible_v<_Err> &&
+               is_trivially_move_constructible_v<_Tp> && is_trivially_move_constructible_v<_Err>)
+    = default;
     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(__union_t&&) = delete;
 
     template <class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t, _Args&&... __args)
@@ -220,6 +229,7 @@ class __expected_base {
     = default;
 
     _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(__repr&&) = delete;
 
     _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
@@ -1081,9 +1091,16 @@ class __expected_void_base {
   // it's not clear that it's implementable, given that the function is allowed to clobber
   // the tail padding) - see https://github.com/itanium-cxx-abi/cxx-abi/issues/107.
   union __union_t {
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = default;
-    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(const __union_t&)
+      requires(is_copy_constructible_v<_Err> && is_trivially_copy_constructible_v<_Err>)
+    = default;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t(__union_t&&)
+      requires(is_move_constructible_v<_Err> && is_trivially_move_constructible_v<_Err>)
+    = default;
     _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(const __union_t&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __union_t& operator=(__union_t&&) = delete;
 
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(in_place_t) : __empty_() {}
 
@@ -1145,6 +1162,7 @@ class __expected_void_base {
     = default;
 
     _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(const __repr&) = delete;
+    _LIBCPP_HIDE_FROM_ABI constexpr __repr& operator=(__repr&&) = delete;
 
     _LIBCPP_HIDE_FROM_ABI constexpr ~__repr()
       requires(is_trivially_destructible_v<_Err>)

>From acb0a3c2a3f2f4a80bd7e35bc4dbf005975b8315 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 26 Oct 2023 07:00:22 +0200
Subject: [PATCH 25/31] fix invalid case style

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

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 529965f60c2cbe9..0208125e07bceb7 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -130,8 +130,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool __expected_can_stuff_tail()
 {
   struct __x {
   private:
-    _LIBCPP_NO_UNIQUE_ADDRESS _Union __union;
-    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val;
+    _LIBCPP_NO_UNIQUE_ADDRESS _Union __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
   return sizeof(__x) == sizeof(_Union);
 }

>From 2bc5ee586ecd19efecfe5be9e3c3a7de7f151db6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 26 Oct 2023 11:35:06 +0200
Subject: [PATCH 26/31] try to fix layout tests for 32-bit platforms

---
 .../expected.expected/no_unique_address.compile.pass.cpp         | 1 +
 .../expected/expected.void/no_unique_address.compile.pass.cpp    | 1 +
 2 files changed, 2 insertions(+)

diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
index 4d523d1ad69500e..cf1909b92873234 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/no_unique_address.compile.pass.cpp
@@ -26,6 +26,7 @@ struct A {
 
 struct B : public A {
   int z_;
+  short z2_;
   virtual ~B() = default;
 };
 
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
index eab2acf1471842e..d533762340d1c68 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/no_unique_address.compile.pass.cpp
@@ -26,6 +26,7 @@ struct A {
 
 struct B : public A {
   int z_;
+  short z2_;
   virtual ~B() = default;
 };
 

>From 83da28481dd521f5617aa6eb51f97272ac821fbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 26 Oct 2023 15:21:25 +0200
Subject: [PATCH 27/31] remove conditional [[no_unique_address]] of union
 members

---
 libcxx/include/__expected/expected.h          | 42 ++++++++-----------
 .../transform_error.mandates.verify.cpp       |  1 +
 .../transform_error.mandates.verify.cpp       |  2 +-
 3 files changed, 20 insertions(+), 25 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 0208125e07bceb7..d817a6bce9a4548 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -88,9 +88,6 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-template <class _Tp>
-concept __expected_union_member_no_unique_address = is_nothrow_move_constructible_v<_Tp>;
-
 struct __expected_invoke_tag {};
 
 template <bool _NoUnique, class _Tp>
@@ -167,12 +164,12 @@ class __expected_base {
     template <class _Func, class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
         std::__expected_construct_in_place_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __val_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+        : __val_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
     template <class _Func, class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
         std::__expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(is_trivially_destructible_v<_Tp> && is_trivially_destructible_v<_Err>)
@@ -181,10 +178,8 @@ class __expected_base {
     // __repr's destructor handles this
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t() {}
 
-    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __expected_union_member_no_unique_address<_Tp>, _Tp>::__type __val_;
-    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __expected_union_member_no_unique_address<_Err>, _Err>::__type __unex_;
+    _LIBCPP_NO_UNIQUE_ADDRESS _Tp __val_;
+    _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
   };
 
   static constexpr bool __can_stuff_tail = __expected_can_stuff_tail<__union_t>();
@@ -289,9 +284,9 @@ class __expected_base {
       requires(!__can_stuff_tail)
     {
       if (__has_val)
-        return __union_t(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
+        return __union_t(in_place, std::forward<_OtherUnion>(__other).__val_);
       else
-        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_);
     }
 
     _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
@@ -304,9 +299,9 @@ class __expected_base {
     requires(__can_stuff_tail)
   {
     if (__has_val)
-      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_.__v);
+      return __repr(in_place, std::forward<_OtherUnion>(__other).__val_);
     else
-      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
   }
 
 protected:
@@ -338,10 +333,10 @@ class __expected_base {
   _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; }
   _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; }
   _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr _Tp& __val() { return __repr_.__v.__union_.__v.__val_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& __val() const { return __repr_.__v.__union_.__v.__val_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Tp& __val() { return __repr_.__v.__union_.__v.__val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& __val() const { return __repr_.__v.__union_.__v.__val_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; }
 
 private:
   _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
@@ -1111,7 +1106,7 @@ class __expected_void_base {
     template <class _Func, class... _Args>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __union_t(
         __expected_construct_unexpected_from_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __unex_(__expected_invoke_tag{}, std::forward<_Func>(__f), std::forward<_Args>(__args)...) {}
+        : __unex_(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
     _LIBCPP_HIDE_FROM_ABI constexpr ~__union_t()
       requires(is_trivially_destructible_v<_Err>)
@@ -1123,8 +1118,7 @@ class __expected_void_base {
     {}
 
     _LIBCPP_NO_UNIQUE_ADDRESS __empty_t __empty_;
-    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __expected_union_member_no_unique_address<_Err>, _Err>::__type __unex_;
+    _LIBCPP_NO_UNIQUE_ADDRESS _Err __unex_;
   };
 
   static constexpr bool __can_stuff_tail = __expected_can_stuff_tail<__union_t>();
@@ -1220,7 +1214,7 @@ class __expected_void_base {
       if (__has_val)
         return __union_t(in_place);
       else
-        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+        return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_);
     }
 
     _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
@@ -1235,7 +1229,7 @@ class __expected_void_base {
     if (__has_val)
       return __repr(in_place);
     else
-      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_.__v);
+      return __repr(unexpect, std::forward<_OtherUnion>(__other).__unex_);
   }
 
 protected:
@@ -1267,8 +1261,8 @@ class __expected_void_base {
   _LIBCPP_HIDE_FROM_ABI constexpr bool __has_val() const { return __repr_.__v.__has_val_; }
   _LIBCPP_HIDE_FROM_ABI constexpr __union_t& __union() { return __repr_.__v.__union_.__v; }
   _LIBCPP_HIDE_FROM_ABI constexpr const __union_t& __union() const { return __repr_.__v.__union_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_.__v; }
-  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_.__v; }
+  _LIBCPP_HIDE_FROM_ABI constexpr _Err& __unex() { return __repr_.__v.__union_.__v.__unex_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; }
 
 private:
   _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
diff --git a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
index 965e82a7b403465..16faddb280d3a33 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp
@@ -48,6 +48,7 @@ void test() {
     e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
+    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
diff --git a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
index 9c8cbcdaaa6d63b..c62673952898726 100644
--- a/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
+++ b/libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp
@@ -49,11 +49,11 @@ void test() {
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
     // expected-error-re@*:* {{call to deleted constructor of {{.*}}}}
+    // expected-error-re@*:* {{union member {{.*}} has reference type {{.*}}}}
 
     e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
     // expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
     // expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
-    // expected-error-re@*:* {{call to deleted constructor of {{.*}}}}
   }
 
   // Test const& overload

>From 1379d6b0841ecba660b40ff502c0b1fa673bcbb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 26 Oct 2023 19:14:01 +0200
Subject: [PATCH 28/31] mark transform tests as failing for GCC

---
 .../expected/expected.expected/monadic/transform.pass.cpp     | 4 ++--
 .../expected.expected/monadic/transform_error.pass.cpp        | 4 ++--
 .../expected/expected.void/monadic/transform_error.pass.cpp   | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp
index f443613fe7f3437..424295bffdf2a21 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform.pass.cpp
@@ -9,8 +9,8 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
 // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
-// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333, but we have a workaround to
-// avoid this issue.
+// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
+// XFAIL: gcc
 
 // <expected>
 
diff --git a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp
index 84b57aea3cd2318..23bf6783a14b1d9 100644
--- a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp
@@ -9,8 +9,8 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
 // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
-// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333, but we have a workaround to
-// avoid this issue.
+// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333.
+// XFAIL: gcc
 
 // <expected>
 
diff --git a/libcxx/test/std/utilities/expected/expected.void/monadic/transform_error.pass.cpp b/libcxx/test/std/utilities/expected/expected.void/monadic/transform_error.pass.cpp
index f0e19ac3c39827c..0c41d11dd66fdbe 100644
--- a/libcxx/test/std/utilities/expected/expected.void/monadic/transform_error.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.void/monadic/transform_error.pass.cpp
@@ -9,8 +9,8 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
 // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`,
-// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333, but we have a workaround to
-// avoid this issue.
+// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333
+// XFAIL: gcc
 
 // <expected>
 

>From cf72c9b6703f26bdc317ee6dff9b9c4fcac263fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Mon, 30 Oct 2023 21:20:59 +0100
Subject: [PATCH 29/31] those two files are now formatted correctly

---
 libcxx/utils/data/ignore_format.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libcxx/utils/data/ignore_format.txt b/libcxx/utils/data/ignore_format.txt
index d4afd8c87350fd1..cf6dca7cd7d3c68 100644
--- a/libcxx/utils/data/ignore_format.txt
+++ b/libcxx/utils/data/ignore_format.txt
@@ -6257,7 +6257,6 @@ libcxx/test/std/utilities/expected/expected.expected/observers/deref.pass.cpp
 libcxx/test/std/utilities/expected/expected.expected/observers/error.pass.cpp
 libcxx/test/std/utilities/expected/expected.expected/observers/has_value.pass.cpp
 libcxx/test/std/utilities/expected/expected.expected/observers/value.pass.cpp
-libcxx/test/std/utilities/expected/expected.expected/swap/member.swap.pass.cpp
 libcxx/test/std/utilities/expected/expected.unexpected/ctad.compile.pass.cpp
 libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.inplace.pass.cpp
 libcxx/test/std/utilities/expected/expected.unexpected/ctor/ctor.move.pass.cpp
@@ -6277,7 +6276,6 @@ libcxx/test/std/utilities/expected/expected.void/observers/deref.pass.cpp
 libcxx/test/std/utilities/expected/expected.void/observers/error.pass.cpp
 libcxx/test/std/utilities/expected/expected.void/observers/has_value.pass.cpp
 libcxx/test/std/utilities/expected/expected.void/swap/free.swap.pass.cpp
-libcxx/test/std/utilities/expected/expected.void/swap/member.swap.pass.cpp
 libcxx/test/std/utilities/format/format.arguments/format.args/get.pass.cpp
 libcxx/test/std/utilities/format/format.arguments/format.args/types.compile.pass.cpp
 libcxx/test/std/utilities/format/format.arguments/format.arg/visit_format_arg.pass.cpp

>From 055ecc3cc203c30eadc79e36a1b276c8db960487 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 2 Nov 2023 20:51:58 +0100
Subject: [PATCH 30/31] simplify __expected_conditional_no_unique_address and
 rename to __conditional_no_unique_address

---
 libcxx/include/__expected/expected.h | 67 +++++++++++++---------------
 1 file changed, 31 insertions(+), 36 deletions(-)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index d817a6bce9a4548..5fab06095d4673c 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -88,38 +88,37 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 #  endif
 }
 
-struct __expected_invoke_tag {};
+struct __conditional_no_unique_address_invoke_tag {};
 
 template <bool _NoUnique, class _Tp>
-class __expected_conditional_no_unique_address {
-  struct __unique {
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __unique(_Args&&... __args)
-        : __v(std::forward<_Args>(__args)...) {}
+struct __conditional_no_unique_address;
 
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __unique(
-        __expected_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+template <class _Tp>
+struct __conditional_no_unique_address<true, _Tp> {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(_Args&&... __args)
+      : __v(std::forward<_Args>(__args)...) {}
 
-    _Tp __v;
-  };
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(
+      __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-  struct __no_unique {
-    template <class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __no_unique(_Args&&... __args)
-        : __v(std::forward<_Args>(__args)...) {}
+  _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
+};
 
-    template <class _Func, class... _Args>
-    _LIBCPP_HIDE_FROM_ABI constexpr explicit __no_unique(
-        __expected_invoke_tag, _Func&& __f, _Args&&... __args)
-        : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+template <class _Tp>
+struct __conditional_no_unique_address<false, _Tp> {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(_Args&&... __args)
+      : __v(std::forward<_Args>(__args)...) {}
 
-    _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
-  };
+  template <class _Func, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(
+      __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
+      : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
 
-public:
-  using __type = std::conditional<_NoUnique, __no_unique, __unique>::type;
+  _Tp __v;
 };
 
 template <class _Union>
@@ -208,7 +207,7 @@ class __expected_base {
     template <class _OtherUnion>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
       requires(!__can_stuff_tail)
-        : __union_(__expected_invoke_tag{},
+        : __union_(__conditional_no_unique_address_invoke_tag{},
               [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
           __has_val_(__has_val) {}
 
@@ -289,8 +288,7 @@ class __expected_base {
         return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_);
     }
 
-    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __can_stuff_tail, __union_t>::__type __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__can_stuff_tail, __union_t> __union_;
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
@@ -312,7 +310,7 @@ class __expected_base {
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_base(bool __has_val, _OtherUnion&& __other)
     requires(__can_stuff_tail)
-      : __repr_(__expected_invoke_tag{},
+      : __repr_(__conditional_no_unique_address_invoke_tag{},
             [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
@@ -339,8 +337,7 @@ class __expected_base {
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; }
 
 private:
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-      !__can_stuff_tail, __repr>::__type __repr_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<!__can_stuff_tail, __repr> __repr_;
 };
 
 template <class _Tp, class _Err>
@@ -1142,7 +1139,7 @@ class __expected_void_base {
     template <class _OtherUnion>
     _LIBCPP_HIDE_FROM_ABI constexpr explicit __repr(bool __has_val, _OtherUnion&& __other)
       requires(!__can_stuff_tail)
-        : __union_(__expected_invoke_tag{},
+        : __union_(__conditional_no_unique_address_invoke_tag{},
               [&] { return __make_union(__has_val, std::forward<_OtherUnion>(__other)); }),
           __has_val_(__has_val) {}
 
@@ -1217,8 +1214,7 @@ class __expected_void_base {
         return __union_t(unexpect, std::forward<_OtherUnion>(__other).__unex_);
     }
 
-    _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-        __can_stuff_tail, __union_t>::__type __union_;
+    _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<__can_stuff_tail, __union_t> __union_;
     _LIBCPP_NO_UNIQUE_ADDRESS bool __has_val_;
   };
 
@@ -1240,7 +1236,7 @@ class __expected_void_base {
   template <class _OtherUnion>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit __expected_void_base(bool __has_val, _OtherUnion&& __other)
     requires(__can_stuff_tail)
-      : __repr_(__expected_invoke_tag{},
+      : __repr_(__conditional_no_unique_address_invoke_tag{},
             [&] { return __make_repr(__has_val, std::forward<_OtherUnion>(__other)); }) {}
 
   _LIBCPP_HIDE_FROM_ABI constexpr void __destroy() {
@@ -1265,8 +1261,7 @@ class __expected_void_base {
   _LIBCPP_HIDE_FROM_ABI constexpr const _Err& __unex() const { return __repr_.__v.__union_.__v.__unex_; }
 
 private:
-  _LIBCPP_NO_UNIQUE_ADDRESS __expected_conditional_no_unique_address<
-      !__can_stuff_tail, __repr>::__type __repr_;
+  _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<!__can_stuff_tail, __repr> __repr_;
 };
 
 template <class _Tp, class _Err>

>From bfb5ef2cdc2694753269fcdd2187b6122426e41a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kokem=C3=BCller?= <jan.kokemueller at gmail.com>
Date: Thu, 2 Nov 2023 20:53:19 +0100
Subject: [PATCH 31/31] add comment to __conditional_no_unique_address
 suggested by ldionne

---
 libcxx/include/__expected/expected.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 5fab06095d4673c..ed8c247e7108084 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -90,6 +90,10 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
 
 struct __conditional_no_unique_address_invoke_tag {};
 
+// This class implements an object with `[[no_unique_address]]` conditionally applied to it,
+// based on the value of `_NoUnique`.
+//
+// If we had a language feature, this class would basically be replaced by `[[no_unique_address(condition)]]`.
 template <bool _NoUnique, class _Tp>
 struct __conditional_no_unique_address;
 



More information about the libcxx-commits mailing list