Skip to content

[libc++] Remove _Lazy#202303

Open
philnik777 wants to merge 1 commit into
llvm:mainfrom
philnik777:avoid_lazy
Open

[libc++] Remove _Lazy#202303
philnik777 wants to merge 1 commit into
llvm:mainfrom
philnik777:avoid_lazy

Conversation

@philnik777

@philnik777 philnik777 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

We don't actually need to evaluate anything as lazily as _Lazy does or we can achieve the same amount of laziness in other ways, so we can get rid of it. This was required previously in some places due to a language defect, which has been resolved and implemented by all compilers we support.

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777 philnik777 marked this pull request as ready for review June 9, 2026 06:28
@philnik777 philnik777 requested a review from a team as a code owner June 9, 2026 06:28
@llvmorg-github-actions llvmorg-github-actions Bot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 9, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

We don't actually need to evaluate anything as lazily as _Lazy does, so we can get rid of it. This was required previously in some places due to a language defect, which has been resolved and implemented by all compilers we support.


Full diff: https://github.com/llvm/llvm-project/pull/202303.diff

7 Files Affected:

  • (modified) libcxx/include/CMakeLists.txt (-1)
  • (modified) libcxx/include/__expected/expected.h (+5-7)
  • (modified) libcxx/include/__type_traits/conjunction.h (+1-1)
  • (modified) libcxx/include/__type_traits/disjunction.h (+1-2)
  • (removed) libcxx/include/__type_traits/lazy.h (-25)
  • (modified) libcxx/include/module.modulemap.in (-1)
  • (modified) libcxx/include/tuple (+21-28)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 10dfb4b4d58cb..1f79769f635da 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -898,7 +898,6 @@ set(files
   __type_traits/is_void.h
   __type_traits/is_volatile.h
   __type_traits/is_within_lifetime.h
-  __type_traits/lazy.h
   __type_traits/make_32_64_or_128_bit.h
   __type_traits/make_const_lvalue_ref.h
   __type_traits/make_signed.h
diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 27bc086698399..32ed81a392702 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -37,7 +37,6 @@
 #include <__type_traits/is_trivially_destructible.h>
 #include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/is_void.h>
-#include <__type_traits/lazy.h>
 #include <__type_traits/negation.h>
 #include <__type_traits/remove_cv.h>
 #include <__type_traits/remove_cvref.h>
@@ -685,12 +684,11 @@ class expected : private __expected_base<_Tp, _Err> {
 private:
   template <class _OtherErrQual>
   static constexpr bool __can_assign_from_unexpected =
-      _And< is_constructible<_Err, _OtherErrQual>,
-            is_assignable<_Err&, _OtherErrQual>,
-            _Lazy<_Or,
-                  is_nothrow_constructible<_Err, _OtherErrQual>,
-                  is_nothrow_move_constructible<_Tp>,
-                  is_nothrow_move_constructible<_Err>> >::value;
+      _And<is_constructible<_Err, _OtherErrQual>,
+           is_assignable<_Err&, _OtherErrQual>,
+           _Or<is_nothrow_constructible<_Err, _OtherErrQual>,
+               is_nothrow_move_constructible<_Tp>,
+               is_nothrow_move_constructible<_Err>>>::value;
 
 public:
   template <class _OtherErr>
diff --git a/libcxx/include/__type_traits/conjunction.h b/libcxx/include/__type_traits/conjunction.h
index ad9656acd47ec..9d84ef8c0ca1b 100644
--- a/libcxx/include/__type_traits/conjunction.h
+++ b/libcxx/include/__type_traits/conjunction.h
@@ -34,7 +34,7 @@ false_type __and_helper(...);
 //
 // However, `_And<_Pred...>` itself will evaluate its result immediately (without having to
 // be instantiated) since it is an alias, unlike `conjunction<_Pred...>`, which is a struct.
-// If you want to defer the evaluation of `_And<_Pred...>` itself, use `_Lazy<_And, _Pred...>`.
+// If you want to defer the evaluation, use `conjunction{,_v}<_Pred...>`.
 template <class... _Pred>
 using _And _LIBCPP_NODEBUG = decltype(std::__and_helper<_Pred...>(0));
 
diff --git a/libcxx/include/__type_traits/disjunction.h b/libcxx/include/__type_traits/disjunction.h
index 8e7a38413a985..40f571a3f0d54 100644
--- a/libcxx/include/__type_traits/disjunction.h
+++ b/libcxx/include/__type_traits/disjunction.h
@@ -38,8 +38,7 @@ struct _OrImpl<false> {
 //
 // However, `_Or<_Pred...>` itself will evaluate its result immediately (without having to
 // be instantiated) since it is an alias, unlike `disjunction<_Pred...>`, which is a struct.
-// If you want to defer the evaluation of `_Or<_Pred...>` itself, use `_Lazy<_Or, _Pred...>`
-// or `disjunction<_Pred...>` directly.
+// If you want to defer the evaluation , use `disjunction{,_v}<_Pred...>`.
 template <class... _Args>
 using _Or _LIBCPP_NODEBUG = typename _OrImpl<sizeof...(_Args) != 0>::template _Result<false_type, _Args...>;
 
diff --git a/libcxx/include/__type_traits/lazy.h b/libcxx/include/__type_traits/lazy.h
deleted file mode 100644
index 80826f1d64f60..0000000000000
--- a/libcxx/include/__type_traits/lazy.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___TYPE_TRAITS_LAZY_H
-#define _LIBCPP___TYPE_TRAITS_LAZY_H
-
-#include <__config>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-template <template <class...> class _Func, class... _Args>
-struct _Lazy : _Func<_Args...> {};
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___TYPE_TRAITS_LAZY_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 29f3818c39671..50d58c76c16bc 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -333,7 +333,6 @@ module std_core [system] {
       export std_core.type_traits.integral_constant
     }
     module is_within_lifetime                         { header "__type_traits/is_within_lifetime.h" }
-    module lazy                                       { header "__type_traits/lazy.h" }
     module make_32_64_or_128_bit                      { header "__type_traits/make_32_64_or_128_bit.h" }
     module make_const_lvalue_ref                      { header "__type_traits/make_const_lvalue_ref.h" }
     module make_signed                                { header "__type_traits/make_signed.h" }
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index d6d9e765934cd..2b32df6bce74a 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -255,7 +255,6 @@ template <class... Types>
 #  include <__type_traits/is_same.h>
 #  include <__type_traits/is_swappable.h>
 #  include <__type_traits/is_trivially_relocatable.h>
-#  include <__type_traits/lazy.h>
 #  include <__type_traits/maybe_const.h>
 #  include <__type_traits/nat.h>
 #  include <__type_traits/negation.h>
@@ -597,30 +596,28 @@ public:
   template <template <class...> class _IsImpDefault                = __is_implicitly_default_constructible,
             template <class...> class _IsDefault                   = is_default_constructible,
             __enable_if_t< _And< _IsDefault<_Tp>... >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(_Not<_Lazy<_And, _IsImpDefault<_Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<_IsImpDefault<_Tp>...>::value)
       tuple() noexcept(_And<is_nothrow_default_constructible<_Tp>...>::value) {}
 
   template <class _Alloc,
             template <class...> class _IsImpDefault                = __is_implicitly_default_constructible,
             template <class...> class _IsDefault                   = is_default_constructible,
             __enable_if_t< _And< _IsDefault<_Tp>... >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, _IsImpDefault<_Tp>...> >::value)
-      tuple(allocator_arg_t, _Alloc const& __a)
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<_IsImpDefault<_Tp>...>::value) tuple(allocator_arg_t, _Alloc const& __a)
       : __base_(allocator_arg_t(), __a, __value_init{}) {}
 
   // tuple(const T&...) constructors (including allocator_arg_t variants)
   template <template <class...> class _And = _And,
             __enable_if_t< _And< _BoolConstant<sizeof...(_Tp) >= 1>, is_copy_constructible<_Tp>... >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI
-  _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<const _Tp&, _Tp>...>::value)
       tuple(const _Tp&... __t) noexcept(_And<is_nothrow_copy_constructible<_Tp>...>::value)
       : __base_(__forward_args{}, __t...) {}
 
   template <class _Alloc,
             template <class...> class _And = _And,
             __enable_if_t< _And< _BoolConstant<sizeof...(_Tp) >= 1>, is_copy_constructible<_Tp>... >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<const _Tp&, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<const _Tp&, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __a, const _Tp&... __t)
       : __base_(allocator_arg_t(), __a, __forward_args{}, __t...) {}
 
@@ -639,7 +636,7 @@ public:
   template <class... _Up,
             __enable_if_t< _And< _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, _EnableUTypesCtor<_Up...> >::value,
                            int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
       tuple(_Up&&... __u) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
       : __base_(__forward_args{}, std::forward<_Up>(__u)...) {}
 
@@ -647,7 +644,7 @@ public:
             class... _Up,
             __enable_if_t< _And< _BoolConstant<sizeof...(_Up) == sizeof...(_Tp)>, _EnableUTypesCtor<_Up...> >::value,
                            int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __a, _Up&&... __u)
       : __base_(allocator_arg_t(), __a, __forward_args{}, std::forward<_Up>(__u)...) {}
 
@@ -685,26 +682,22 @@ public:
             _Not<is_same<_OtherTuple, const tuple&> >,
             _Not<is_same<_OtherTuple, tuple&&> >,
             is_constructible<_Tp, __copy_cvref_t<_OtherTuple, _Up> >...,
-            _Lazy<_Or,
-                  _BoolConstant<sizeof...(_Tp) != 1>,
-                  // _Tp and _Up are 1-element packs - the pack expansions look
-                  // weird to avoid tripping up the type traits in degenerate cases
-                  _Lazy<_And,
-                        _Not<is_same<_Tp, _Up> >...,
-                        _Not<is_convertible<_OtherTuple, _Tp> >...,
-                        _Not<is_constructible<_Tp, _OtherTuple> >... > > > {};
+            _Or<_BoolConstant<sizeof...(_Tp) != 1>,
+                // _Tp and _Up are 1-element packs - the pack expansions look
+                // weird to avoid tripping up the type traits in degenerate cases
+                _And<_Not<is_same<_Tp, _Up> >...,
+                     _Not<is_convertible<_OtherTuple, _Tp> >...,
+                     _Not<is_constructible<_Tp, _OtherTuple> >... > > > {};
 
   template <class... _Up, __enable_if_t< _And< _EnableCtorFromUTypesTuple<const tuple<_Up...>&> >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI
-  _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
       tuple(const tuple<_Up...>& __t) noexcept(_And<is_nothrow_constructible<_Tp, const _Up&>...>::value)
       : __base_(__from_tuple(), __t) {}
 
   template <class... _Up,
             class _Alloc,
             __enable_if_t< _And< _EnableCtorFromUTypesTuple<const tuple<_Up...>&> >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<const _Up&, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<const _Up&, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __a, const tuple<_Up...>& __t)
       : __base_(allocator_arg_t(), __a, __from_tuple(), __t) {}
 
@@ -712,25 +705,25 @@ public:
   // tuple(tuple<U...>&) constructors (including allocator_arg_t variants)
 
   template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value) tuple(tuple<_Up...>& __t)
       : __base_(__from_tuple(), __t) {}
 
   template <class _Alloc, class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<tuple<_Up...>&>::value>* = nullptr>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<_Up&, _Tp>...>::value)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<_Up&, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __alloc, tuple<_Up...>& __t)
       : __base_(allocator_arg_t(), __alloc, __from_tuple(), __t) {}
 #    endif // _LIBCPP_STD_VER >= 23
 
   // tuple(tuple<U...>&&) constructors (including allocator_arg_t variants)
   template <class... _Up, __enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
       tuple(tuple<_Up...>&& __t) noexcept(_And<is_nothrow_constructible<_Tp, _Up>...>::value)
       : __base_(__from_tuple(), std::move(__t)) {}
 
   template <class _Alloc,
             class... _Up,
             __enable_if_t< _And< _EnableCtorFromUTypesTuple<tuple<_Up...>&&> >::value, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(_Not<_Lazy<_And, is_convertible<_Up, _Tp>...> >::value)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!_And<is_convertible<_Up, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __a, tuple<_Up...>&& __t)
       : __base_(allocator_arg_t(), __a, __from_tuple(), std::move(__t)) {}
 
@@ -738,14 +731,14 @@ public:
   // tuple(const tuple<U...>&&) constructors (including allocator_arg_t variants)
 
   template <class... _Up, enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
       tuple(const tuple<_Up...>&& __t)
       : __base_(__from_tuple(), std::move(__t)) {}
 
   template <class _Alloc,
             class... _Up,
             enable_if_t< _EnableCtorFromUTypesTuple<const tuple<_Up...>&&>::value>* = nullptr>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_Lazy<_And, is_convertible<const _Up&&, _Tp>...>::value)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_And<is_convertible<const _Up&&, _Tp>...>::value)
       tuple(allocator_arg_t, const _Alloc& __alloc, const tuple<_Up...>&& __t)
       : __base_(allocator_arg_t(), __alloc, __from_tuple(), std::move(__t)) {}
 #    endif // _LIBCPP_STD_VER >= 23

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant