-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] views::split
and views::lazy_split
shouldn't be range adaptor closures
#75266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This was failing with: D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(42,1): error: static assertion failed static_assert( CanBePiped<SomeView&, decltype(std::views::split)>); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(42,16): note: because 'CanBePiped<SomeView &, decltype(std::views::split)>' evaluated to false static_assert( CanBePiped<SomeView&, decltype(std::views::split)>); ^ D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(25,30): note: because 'std::forward<View>(view) | std::forward<T>(t)' would be invalid: invalid operands to binary expression ('SomeView' and 'const std::ranges::views::_Split_fn') { std::forward<View>(view) | std::forward<T>(t) }; ^ D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(43,1): error: static assertion failed static_assert( CanBePiped<char(&)[10], decltype(std::views::split)>); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(43,16): note: because 'CanBePiped<char (&)[10], decltype(std::views::split)>' evaluated to false static_assert( CanBePiped<char(&)[10], decltype(std::views::split)>); ^ D:\GitHub\STL\llvm-project\libcxx\test\std\ranges\range.adaptors\range.split\adaptor.pass.cpp(25,30): note: because 'std::forward<View>(view) | std::forward<T>(t)' would be invalid: invalid operands to binary expression ('char[10]' and 'const std::ranges::views::_Split_fn') { std::forward<View>(view) | std::forward<T>(t) }; ^ Similarly for range.lazy.split/adaptor.pass.cpp.
@llvm/pr-subscribers-libcxx Author: Stephan T. Lavavej (StephanTLavavej) ChangesFixes #75002. Found while running libc++'s tests with MSVC's STL. This is a superset of #74961 that also attempts to fix the product code and add a regression test. Thanks again, @cpplearner! <details><summary>Click to expand Standardese citations:</summary>
To summarize: This PR adjusts the test coverage accordingly, allowing it to portably pass for libc++ and MSVC's STL. <details><summary>Click to expand the Clang compiler error that discovered this:</summary>
</details> Full diff: https://github.com/llvm/llvm-project/pull/75266.diff 4 Files Affected:
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index 2c654bfd325a63..8ed4bcfdeb56d4 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -437,7 +437,7 @@ lazy_split_view(_Range&&, range_value_t<_Range>)
namespace views {
namespace __lazy_split_view {
-struct __fn : __range_adaptor_closure<__fn> {
+struct __fn {
template <class _Range, class _Pattern>
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Range&& __range, _Pattern&& __pattern) const
diff --git a/libcxx/include/__ranges/split_view.h b/libcxx/include/__ranges/split_view.h
index a27ac4ef7a1965..7f03be3c346a42 100644
--- a/libcxx/include/__ranges/split_view.h
+++ b/libcxx/include/__ranges/split_view.h
@@ -194,7 +194,7 @@ struct split_view<_View, _Pattern>::__sentinel {
namespace views {
namespace __split_view {
-struct __fn : __range_adaptor_closure<__fn> {
+struct __fn {
// clang-format off
template <class _Range, class _Pattern>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/adaptor.pass.cpp
index da4bd9fbbe1794..6bfa0ab487ba1b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/adaptor.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/adaptor.pass.cpp
@@ -40,10 +40,16 @@ static_assert(!std::is_invocable_v<decltype(std::views::lazy_split), SomeView, N
static_assert(!std::is_invocable_v<decltype(std::views::lazy_split), NotAView, SomeView>);
static_assert( std::is_invocable_v<decltype(std::views::lazy_split), SomeView, SomeView>);
-static_assert( CanBePiped<SomeView&, decltype(std::views::lazy_split)>);
-static_assert( CanBePiped<char(&)[10], decltype(std::views::lazy_split)>);
-static_assert(!CanBePiped<char(&&)[10], decltype(std::views::lazy_split)>);
-static_assert(!CanBePiped<NotAView, decltype(std::views::lazy_split)>);
+// Regression test for #75002, views::lazy_split shouldn't be a range adaptor closure
+static_assert(!CanBePiped<SomeView&, decltype(std::views::lazy_split)>);
+static_assert(!CanBePiped<char (&)[10], decltype(std::views::lazy_split)>);
+static_assert(!CanBePiped<char (&&)[10], decltype(std::views::lazy_split)>);
+static_assert(!CanBePiped<NotAView, decltype(std::views::lazy_split)>);
+
+static_assert(CanBePiped<SomeView&, decltype(std::views::lazy_split('x'))>);
+static_assert(CanBePiped<char (&)[10], decltype(std::views::lazy_split('x'))>);
+static_assert(!CanBePiped<char (&&)[10], decltype(std::views::lazy_split('x'))>);
+static_assert(!CanBePiped<NotAView, decltype(std::views::lazy_split('x'))>);
static_assert(std::same_as<decltype(std::views::lazy_split), decltype(std::ranges::views::lazy_split)>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.split/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.split/adaptor.pass.cpp
index cd12011daeab5d..85d13ac5c29dfb 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.split/adaptor.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.split/adaptor.pass.cpp
@@ -39,10 +39,16 @@ static_assert(!std::is_invocable_v<decltype(std::views::split), SomeView, NotAVi
static_assert(!std::is_invocable_v<decltype(std::views::split), NotAView, SomeView>);
static_assert( std::is_invocable_v<decltype(std::views::split), SomeView, SomeView>);
-static_assert( CanBePiped<SomeView&, decltype(std::views::split)>);
-static_assert( CanBePiped<char(&)[10], decltype(std::views::split)>);
-static_assert(!CanBePiped<char(&&)[10], decltype(std::views::split)>);
-static_assert(!CanBePiped<NotAView, decltype(std::views::split)>);
+// Regression test for #75002, views::split shouldn't be a range adaptor closure
+static_assert(!CanBePiped<SomeView&, decltype(std::views::split)>);
+static_assert(!CanBePiped<char (&)[10], decltype(std::views::split)>);
+static_assert(!CanBePiped<char (&&)[10], decltype(std::views::split)>);
+static_assert(!CanBePiped<NotAView, decltype(std::views::split)>);
+
+static_assert(CanBePiped<SomeView&, decltype(std::views::split('x'))>);
+static_assert(CanBePiped<char (&)[10], decltype(std::views::split('x'))>);
+static_assert(!CanBePiped<char (&&)[10], decltype(std::views::split('x'))>);
+static_assert(!CanBePiped<NotAView, decltype(std::views::split('x'))>);
static_assert(std::same_as<decltype(std::views::split), decltype(std::ranges::views::split)>);
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Checks passed with only unrelated sporadic failures/timeouts on Android, merging this now. |
Fixes #75002. Found while running libc++'s tests with MSVC's STL.
This is a superset of #74961 that also attempts to fix the product code and add a regression test. Thanks again, @cpplearner!
Click to expand Standardese citations:
To summarize:
views::split
andviews::lazy_split
aren't unary, aren't range adaptor closure objects, and can't be piped. However, [range.adaptor.object]/8 says thatviews::split(pattern)
andviews::lazy_split(pattern)
produce unary, pipeable, range adaptor closure objects.This PR adjusts the test coverage accordingly, allowing it to portably pass for libc++ and MSVC's STL.
Click to expand the Clang compiler error that discovered this: