Skip to content

[libc++] P2602R2 Poison Pills are Too Toxic #74534

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

Merged
merged 23 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
aaccb9e
[libc++] P2602R2 Poison Pills are Too Toxic
JMazurkiewicz Dec 5, 2023
912bc3e
Make 🐍 formatter happy
JMazurkiewicz Dec 5, 2023
079d0e6
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Jan 10, 2024
aabffdd
Formatting
JMazurkiewicz Jan 10, 2024
ccfae95
Formatting (again)
JMazurkiewicz Jan 10, 2024
5f0ad59
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 3, 2024
0b5275c
Code cleanup
JMazurkiewicz Feb 3, 2024
7562e18
Update docs
JMazurkiewicz Feb 5, 2024
caa3aca
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 5, 2024
9429bbf
Fix value of `__cpp_lib_ranges` FTM
JMazurkiewicz Feb 20, 2024
7680d14
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 20, 2024
d908384
Python formatting
JMazurkiewicz Feb 20, 2024
fec6936
Poke CI
JMazurkiewicz Feb 20, 2024
f0c2fe5
Poke CI (again)
JMazurkiewicz Feb 21, 2024
0df473e
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 22, 2024
510a91a
Separate ordinary unqualified lookup tests.
JMazurkiewicz Feb 26, 2024
a1dbe7d
Revert changes to `__cpp_lib_ranges`
JMazurkiewicz Feb 26, 2024
6201b0f
Whitespace cleanup
JMazurkiewicz Feb 26, 2024
58a8e52
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 26, 2024
84ca8f2
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Feb 27, 2024
191568d
Merge `robust_against_ordinary_unqualified_lookup.compile.pass.cpp` t…
JMazurkiewicz Mar 7, 2024
2d54041
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Mar 7, 2024
5328845
Merge branch 'main' into libcxx/ranges/poison-pills
JMazurkiewicz Mar 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"`P2396R1 <https://wg21.link/P2396R1>`__","LWG", "Concurrency TS 2 fixes ", "November 2022","","","|concurrency TS|"
"`P2505R5 <https://wg21.link/P2505R5>`__","LWG", "Monadic Functions for ``std::expected``", "November 2022","|Complete|","17.0",""
"`P2539R4 <https://wg21.link/P2539R4>`__","LWG", "Should the output of ``std::print`` to a terminal be synchronized with the underlying stream?", "November 2022","|Complete|","18.0","|format|"
"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","","","|ranges|"
"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","|Complete|","19.0","|ranges|"
"`P2708R1 <https://wg21.link/P2708R1>`__","LWG", "No Further Fundamentals TSes", "November 2022","|Nothing to do|","",""
"","","","","","",""
"`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|"
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/__compare/partial_order.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// [cmp.alg]
namespace __partial_order {
void partial_order() = delete;

struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here
template <class _Tp, class _Up>
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/__compare/strong_order.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// [cmp.alg]
namespace __strong_order {
void strong_order() = delete;

struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here
template <class _Tp, class _Up>
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/__compare/weak_order.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// [cmp.alg]
namespace __weak_order {
void weak_order() = delete;

struct __fn {
// NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here
template <class _Tp, class _Up>
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__iterator/iter_move.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
namespace __iter_move {

void iter_move();
void iter_move() = delete;

template <class _Tp>
concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
Expand Down
6 changes: 2 additions & 4 deletions libcxx/include/__ranges/access.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ concept __member_begin = __can_borrow<_Tp> && __workaround_52970<_Tp> && require
{ _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
};

void begin(auto&) = delete;
void begin(const auto&) = delete;
void begin() = delete;

template <class _Tp>
concept __unqualified_begin =
Expand Down Expand Up @@ -109,8 +108,7 @@ concept __member_end = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires(
{ _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
};

void end(auto&) = delete;
void end(const auto&) = delete;
void end() = delete;

template <class _Tp>
concept __unqualified_end =
Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__ranges/rbegin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ concept __member_rbegin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requir
{ _LIBCPP_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator;
};

void rbegin(auto&) = delete;
void rbegin(const auto&) = delete;
void rbegin() = delete;

template <class _Tp>
concept __unqualified_rbegin =
Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__ranges/rend.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ concept __member_rend = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires
{ _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
};

void rend(auto&) = delete;
void rend(const auto&) = delete;
void rend() = delete;

template <class _Tp>
concept __unqualified_rend =
Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__ranges/size.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ inline constexpr bool disable_sized_range = false;

namespace ranges {
namespace __size {
void size(auto&) = delete;
void size(const auto&) = delete;
void size() = delete;

template <class _Tp>
concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, HasIterSwap&>);
static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, int&>);
static_assert(!std::is_invocable_v<IterSwapT&&, int&, HasIterSwap&>);

struct StructWithNotMoreSpecializedIterSwap {
friend void iter_swap(auto&, auto&);
};

static_assert(
!std::is_invocable_v<IterSwapT, StructWithNotMoreSpecializedIterSwap&, StructWithNotMoreSpecializedIterSwap&>);

struct NodiscardIterSwap {
[[nodiscard]] friend int iter_swap(NodiscardIterSwap&, NodiscardIterSwap&) { return 0; }
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// <iterator>

// Ordinary unqualified lookup should not be performed.

namespace ns {
struct StructWithGlobalIterCustFunctions {};
} // namespace ns

int&& iter_move(ns::StructWithGlobalIterCustFunctions);
void iter_swap(ns::StructWithGlobalIterCustFunctions, ns::StructWithGlobalIterCustFunctions);

#include <iterator>
#include <type_traits>

static_assert(!std::is_invocable_v<decltype(std::ranges::iter_move), ns::StructWithGlobalIterCustFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::iter_swap),
ns::StructWithGlobalIterCustFunctions&,
ns::StructWithGlobalIterCustFunctions&>);
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// <compare>

// Ordinary unqualified lookup should not be performed.

namespace ns {
struct StructWithGlobalCmpFunctions {};
} // namespace ns

struct ConvertibleToCmpType;

ConvertibleToCmpType strong_order(ns::StructWithGlobalCmpFunctions, ns::StructWithGlobalCmpFunctions);
ConvertibleToCmpType weak_order(ns::StructWithGlobalCmpFunctions, ns::StructWithGlobalCmpFunctions);
ConvertibleToCmpType partial_order(ns::StructWithGlobalCmpFunctions, ns::StructWithGlobalCmpFunctions);

#include <compare>
#include <type_traits>

struct ConvertibleToCmpType {
operator std::strong_ordering() const;
operator std::weak_ordering() const;
operator std::partial_ordering() const;
};

static_assert(!std::is_invocable_v<decltype(std::strong_order),
ns::StructWithGlobalCmpFunctions,
ns::StructWithGlobalCmpFunctions>);
static_assert(!std::is_invocable_v<decltype(std::weak_order),
ns::StructWithGlobalCmpFunctions,
ns::StructWithGlobalCmpFunctions>);
static_assert(!std::is_invocable_v<decltype(std::partial_order),
ns::StructWithGlobalCmpFunctions,
ns::StructWithGlobalCmpFunctions>);
10 changes: 5 additions & 5 deletions libcxx/test/std/ranges/range.access/begin.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ struct BeginFunction {
};
static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>);
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>);
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &>);
static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);

Expand Down Expand Up @@ -245,7 +245,7 @@ struct BeginFunctionWithPrivateBeginMember {
constexpr bool testBeginFunction() {
BeginFunction a{};
const BeginFunction aa{};
static_assert(!std::invocable<RangeBeginT, decltype((a))>);
assert(std::ranges::begin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(a) == &a.x);
assert(std::ranges::begin(aa) == &aa.x);
assert(std::ranges::cbegin(aa) == &aa.x);
Expand All @@ -266,21 +266,21 @@ constexpr bool testBeginFunction() {

BeginFunctionReturnsEmptyPtr d{};
const BeginFunctionReturnsEmptyPtr dd{};
static_assert(!std::invocable<RangeBeginT, decltype((d))>);
assert(std::ranges::begin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(d) == &d.x);
assert(std::ranges::begin(dd) == &dd.x);
assert(std::ranges::cbegin(dd) == &dd.x);

BeginFunctionWithDataMember e{};
const BeginFunctionWithDataMember ee{};
static_assert(!std::invocable<RangeBeginT, decltype((e))>);
assert(std::ranges::begin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::begin(ee) == &ee.x);
assert(std::ranges::cbegin(e) == &e.x);
assert(std::ranges::cbegin(ee) == &ee.x);

BeginFunctionWithPrivateBeginMember f{};
const BeginFunctionWithPrivateBeginMember ff{};
static_assert(!std::invocable<RangeBeginT, decltype((f))>);
assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cbegin(f) == &f.y);
assert(std::ranges::begin(ff) == &ff.y);
assert(std::ranges::cbegin(ff) == &ff.y);
Expand Down
12 changes: 6 additions & 6 deletions libcxx/test/std/ranges/range.access/end.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);

static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &>);
static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);
static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);

Expand Down Expand Up @@ -271,7 +271,7 @@ constexpr bool testEndFunction() {
assert(std::ranges::end(a) == &a.x);
assert(std::ranges::cend(a) == &a.x);
EndFunction aa{};
static_assert(!std::is_invocable_v<RangeEndT, decltype((aa))>);
assert(std::ranges::end(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(aa) == &aa.x);

EndFunctionByValue b;
Expand All @@ -286,28 +286,28 @@ constexpr bool testEndFunction() {
assert(std::ranges::end(d) == &d.x);
assert(std::ranges::cend(d) == &d.x);
EndFunctionReturnsEmptyPtr dd{};
static_assert(!std::is_invocable_v<RangeEndT, decltype((dd))>);
assert(std::ranges::end(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(dd) == &dd.x);

const EndFunctionWithDataMember e{};
assert(std::ranges::end(e) == &e.x);
assert(std::ranges::cend(e) == &e.x);
EndFunctionWithDataMember ee{};
static_assert(!std::is_invocable_v<RangeEndT, decltype((ee))>);
assert(std::ranges::end(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(ee) == &ee.x);

const EndFunctionWithPrivateEndMember f{};
assert(std::ranges::end(f) == &f.y);
assert(std::ranges::cend(f) == &f.y);
EndFunctionWithPrivateEndMember ff{};
static_assert(!std::is_invocable_v<RangeEndT, decltype((ff))>);
assert(std::ranges::end(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(ff) == &ff.y);

const BeginMemberEndFunction g{};
assert(std::ranges::end(g) == &g.x);
assert(std::ranges::cend(g) == &g.x);
BeginMemberEndFunction gg{};
static_assert(!std::is_invocable_v<RangeEndT, decltype((gg))>);
assert(std::ranges::end(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::cend(gg) == &gg.x);

return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// <ranges>

// Ordinary unqualified lookup should not be performed.

namespace ns {
struct StructWithGlobalRangeAccessFunctions {};
} // namespace ns

int* begin(ns::StructWithGlobalRangeAccessFunctions);
int* end(ns::StructWithGlobalRangeAccessFunctions);
int* rbegin(ns::StructWithGlobalRangeAccessFunctions);
int* rend(ns::StructWithGlobalRangeAccessFunctions);
unsigned int size(ns::StructWithGlobalRangeAccessFunctions);

#include <ranges>
#include <type_traits>

static_assert(!std::is_invocable_v<decltype(std::ranges::begin), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::cbegin), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::end), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::cend), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::rbegin), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::crbegin), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::rend), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::crend), ns::StructWithGlobalRangeAccessFunctions&>);
static_assert(!std::is_invocable_v<decltype(std::ranges::size), ns::StructWithGlobalRangeAccessFunctions&>);
11 changes: 6 additions & 5 deletions libcxx/test/std/ranges/range.access/rbegin.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ struct RBeginFunction {
};
static_assert( std::is_invocable_v<RangeRBeginT, RBeginFunction const&>);
static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &&>);
static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &>);
static_assert(
std::is_invocable_v<RangeRBeginT, RBeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction const&>);
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction &>);

Expand Down Expand Up @@ -246,7 +247,7 @@ struct RBeginFunctionWithPrivateBeginMember {
constexpr bool testRBeginFunction() {
RBeginFunction a{};
const RBeginFunction aa{};
static_assert(!std::invocable<RangeRBeginT, decltype((a))>);
assert(std::ranges::rbegin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(a) == &a.x);
assert(std::ranges::rbegin(aa) == &aa.x);
assert(std::ranges::crbegin(aa) == &aa.x);
Expand All @@ -267,21 +268,21 @@ constexpr bool testRBeginFunction() {

RBeginFunctionReturnsEmptyPtr d{};
const RBeginFunctionReturnsEmptyPtr dd{};
static_assert(!std::invocable<RangeRBeginT, decltype((d))>);
assert(std::ranges::rbegin(d) == &d.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(d) == &d.x);
assert(std::ranges::rbegin(dd) == &dd.x);
assert(std::ranges::crbegin(dd) == &dd.x);

RBeginFunctionWithDataMember e{};
const RBeginFunctionWithDataMember ee{};
static_assert(!std::invocable<RangeRBeginT, decltype((e))>);
assert(std::ranges::rbegin(e) == &e.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::rbegin(ee) == &ee.x);
assert(std::ranges::crbegin(e) == &e.x);
assert(std::ranges::crbegin(ee) == &ee.x);

RBeginFunctionWithPrivateBeginMember f{};
const RBeginFunctionWithPrivateBeginMember ff{};
static_assert(!std::invocable<RangeRBeginT, decltype((f))>);
assert(std::ranges::rbegin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
assert(std::ranges::crbegin(f) == &f.y);
assert(std::ranges::rbegin(ff) == &ff.y);
assert(std::ranges::crbegin(ff) == &ff.y);
Expand Down
Loading