Skip to content

Commit 12978b3

Browse files
[libc++] P2602R2 Poison Pills are Too Toxic (#74534)
Implements [P2602R2 Poison Pills are Too Toxic](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2602r2.html) as a DR in C++20 mode.
1 parent 8e69052 commit 12978b3

File tree

16 files changed

+147
-35
lines changed

16 files changed

+147
-35
lines changed

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
"`P2396R1 <https://wg21.link/P2396R1>`__","LWG", "Concurrency TS 2 fixes ", "November 2022","","","|concurrency TS|"
101101
"`P2505R5 <https://wg21.link/P2505R5>`__","LWG", "Monadic Functions for ``std::expected``", "November 2022","|Complete|","17.0",""
102102
"`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|"
103-
"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","","","|ranges|"
103+
"`P2602R2 <https://wg21.link/P2602R2>`__","LWG", "Poison Pills are Too Toxic", "November 2022","|Complete|","19.0","|ranges|"
104104
"`P2708R1 <https://wg21.link/P2708R1>`__","LWG", "No Further Fundamentals TSes", "November 2022","|Nothing to do|","",""
105105
"","","","","","",""
106106
"`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|"

libcxx/include/__compare/partial_order.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2828

2929
// [cmp.alg]
3030
namespace __partial_order {
31+
void partial_order() = delete;
32+
3133
struct __fn {
3234
// NOLINTBEGIN(libcpp-robust-against-adl) partial_order should use ADL, but only here
3335
template <class _Tp, class _Up>

libcxx/include/__compare/strong_order.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3737

3838
// [cmp.alg]
3939
namespace __strong_order {
40+
void strong_order() = delete;
41+
4042
struct __fn {
4143
// NOLINTBEGIN(libcpp-robust-against-adl) strong_order should use ADL, but only here
4244
template <class _Tp, class _Up>

libcxx/include/__compare/weak_order.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3030

3131
// [cmp.alg]
3232
namespace __weak_order {
33+
void weak_order() = delete;
34+
3335
struct __fn {
3436
// NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here
3537
template <class _Tp, class _Up>

libcxx/include/__iterator/iter_move.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3535
namespace ranges {
3636
namespace __iter_move {
3737

38-
void iter_move();
38+
void iter_move() = delete;
3939

4040
template <class _Tp>
4141
concept __unqualified_iter_move = __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {

libcxx/include/__ranges/access.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ concept __member_begin = __can_borrow<_Tp> && __workaround_52970<_Tp> && require
4545
{ _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
4646
};
4747

48-
void begin(auto&) = delete;
49-
void begin(const auto&) = delete;
48+
void begin() = delete;
5049

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

112-
void end(auto&) = delete;
113-
void end(const auto&) = delete;
111+
void end() = delete;
114112

115113
template <class _Tp>
116114
concept __unqualified_end =

libcxx/include/__ranges/rbegin.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ concept __member_rbegin = __can_borrow<_Tp> && __workaround_52970<_Tp> && requir
4040
{ _LIBCPP_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator;
4141
};
4242

43-
void rbegin(auto&) = delete;
44-
void rbegin(const auto&) = delete;
43+
void rbegin() = delete;
4544

4645
template <class _Tp>
4746
concept __unqualified_rbegin =

libcxx/include/__ranges/rend.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ concept __member_rend = __can_borrow<_Tp> && __workaround_52970<_Tp> && requires
4242
{ _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>;
4343
};
4444

45-
void rend(auto&) = delete;
46-
void rend(const auto&) = delete;
45+
void rend() = delete;
4746

4847
template <class _Tp>
4948
concept __unqualified_rend =

libcxx/include/__ranges/size.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ inline constexpr bool disable_sized_range = false;
4141

4242
namespace ranges {
4343
namespace __size {
44-
void size(auto&) = delete;
45-
void size(const auto&) = delete;
44+
void size() = delete;
4645

4746
template <class _Tp>
4847
concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;

libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.swap/iter_swap.pass.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, HasIterSwap&>);
4747
static_assert( std::is_invocable_v<IterSwapT&&, HasIterSwap&, int&>);
4848
static_assert(!std::is_invocable_v<IterSwapT&&, int&, HasIterSwap&>);
4949

50+
struct StructWithNotMoreSpecializedIterSwap {
51+
friend void iter_swap(auto&, auto&);
52+
};
53+
54+
static_assert(
55+
!std::is_invocable_v<IterSwapT, StructWithNotMoreSpecializedIterSwap&, StructWithNotMoreSpecializedIterSwap&>);
56+
5057
struct NodiscardIterSwap {
5158
[[nodiscard]] friend int iter_swap(NodiscardIterSwap&, NodiscardIterSwap&) { return 0; }
5259
};

libcxx/test/std/ranges/range.access/begin.pass.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ struct BeginFunction {
192192
};
193193
static_assert( std::is_invocable_v<RangeBeginT, BeginFunction const&>);
194194
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &&>);
195-
static_assert(!std::is_invocable_v<RangeBeginT, BeginFunction &>);
195+
static_assert(std::is_invocable_v<RangeBeginT, BeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
196196
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction const&>);
197197
static_assert( std::is_invocable_v<RangeCBeginT, BeginFunction &>);
198198

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

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

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

281281
BeginFunctionWithPrivateBeginMember f{};
282282
const BeginFunctionWithPrivateBeginMember ff{};
283-
static_assert(!std::invocable<RangeBeginT, decltype((f))>);
283+
assert(std::ranges::begin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
284284
assert(std::ranges::cbegin(f) == &f.y);
285285
assert(std::ranges::begin(ff) == &ff.y);
286286
assert(std::ranges::cbegin(ff) == &ff.y);

libcxx/test/std/ranges/range.access/end.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
193193

194194
static_assert( std::is_invocable_v<RangeEndT, EndFunction const&>);
195195
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &&>);
196-
static_assert(!std::is_invocable_v<RangeEndT, EndFunction &>);
196+
static_assert(std::is_invocable_v<RangeEndT, EndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
197197
static_assert( std::is_invocable_v<RangeCEndT, EndFunction const&>);
198198
static_assert( std::is_invocable_v<RangeCEndT, EndFunction &>);
199199

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

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

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

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

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

313313
return true;

libcxx/test/std/ranges/range.access/rbegin.pass.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ struct RBeginFunction {
187187
};
188188
static_assert( std::is_invocable_v<RangeRBeginT, RBeginFunction const&>);
189189
static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &&>);
190-
static_assert(!std::is_invocable_v<RangeRBeginT, RBeginFunction &>);
190+
static_assert(
191+
std::is_invocable_v<RangeRBeginT, RBeginFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
191192
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction const&>);
192193
static_assert( std::is_invocable_v<RangeCRBeginT, RBeginFunction &>);
193194

@@ -246,7 +247,7 @@ struct RBeginFunctionWithPrivateBeginMember {
246247
constexpr bool testRBeginFunction() {
247248
RBeginFunction a{};
248249
const RBeginFunction aa{};
249-
static_assert(!std::invocable<RangeRBeginT, decltype((a))>);
250+
assert(std::ranges::rbegin(a) == &a.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
250251
assert(std::ranges::crbegin(a) == &a.x);
251252
assert(std::ranges::rbegin(aa) == &aa.x);
252253
assert(std::ranges::crbegin(aa) == &aa.x);
@@ -267,21 +268,21 @@ constexpr bool testRBeginFunction() {
267268

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

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

282283
RBeginFunctionWithPrivateBeginMember f{};
283284
const RBeginFunctionWithPrivateBeginMember ff{};
284-
static_assert(!std::invocable<RangeRBeginT, decltype((f))>);
285+
assert(std::ranges::rbegin(f) == &f.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
285286
assert(std::ranges::crbegin(f) == &f.y);
286287
assert(std::ranges::rbegin(ff) == &ff.y);
287288
assert(std::ranges::crbegin(ff) == &ff.y);

libcxx/test/std/ranges/range.access/rend.pass.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>);
196196

197197
static_assert( std::is_invocable_v<RangeREndT, REndFunction const&>);
198198
static_assert(!std::is_invocable_v<RangeREndT, REndFunction &&>);
199-
static_assert(!std::is_invocable_v<RangeREndT, REndFunction &>);
199+
static_assert(std::is_invocable_v<RangeREndT, REndFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
200200
static_assert( std::is_invocable_v<RangeCREndT, REndFunction const&>);
201201
static_assert( std::is_invocable_v<RangeCREndT, REndFunction &>);
202202

@@ -272,7 +272,7 @@ constexpr bool testREndFunction() {
272272
assert(std::ranges::rend(a) == &a.x);
273273
assert(std::ranges::crend(a) == &a.x);
274274
REndFunction aa{};
275-
static_assert(!std::is_invocable_v<RangeREndT, decltype((aa))>);
275+
assert(std::ranges::rend(aa) == &aa.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
276276
assert(std::ranges::crend(aa) == &aa.x);
277277

278278
REndFunctionByValue b;
@@ -287,28 +287,28 @@ constexpr bool testREndFunction() {
287287
assert(std::ranges::rend(d) == &d.x);
288288
assert(std::ranges::crend(d) == &d.x);
289289
REndFunctionReturnsEmptyPtr dd{};
290-
static_assert(!std::is_invocable_v<RangeREndT, decltype((dd))>);
290+
assert(std::ranges::rend(dd) == &dd.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
291291
assert(std::ranges::crend(dd) == &dd.x);
292292

293293
const REndFunctionWithDataMember e{};
294294
assert(std::ranges::rend(e) == &e.x);
295295
assert(std::ranges::crend(e) == &e.x);
296296
REndFunctionWithDataMember ee{};
297-
static_assert(!std::is_invocable_v<RangeREndT, decltype((ee))>);
297+
assert(std::ranges::rend(ee) == &ee.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
298298
assert(std::ranges::crend(ee) == &ee.x);
299299

300300
const REndFunctionWithPrivateEndMember f{};
301301
assert(std::ranges::rend(f) == &f.y);
302302
assert(std::ranges::crend(f) == &f.y);
303303
REndFunctionWithPrivateEndMember ff{};
304-
static_assert(!std::is_invocable_v<RangeREndT, decltype((ff))>);
304+
assert(std::ranges::rend(ff) == &ff.y); // Ill-formed before P2602R2 Poison Pills are Too Toxic
305305
assert(std::ranges::crend(ff) == &ff.y);
306306

307307
const RBeginMemberEndFunction g{};
308308
assert(std::ranges::rend(g) == &g.x);
309309
assert(std::ranges::crend(g) == &g.x);
310310
RBeginMemberEndFunction gg{};
311-
static_assert(!std::is_invocable_v<RangeREndT, decltype((gg))>);
311+
assert(std::ranges::rend(gg) == &gg.x); // Ill-formed before P2602R2 Poison Pills are Too Toxic
312312
assert(std::ranges::crend(gg) == &gg.x);
313313

314314
return true;

libcxx/test/std/ranges/range.access/size.pass.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,8 @@ inline constexpr bool std::ranges::disable_sized_range<const ImproperlyDisabledF
219219

220220
static_assert( std::is_invocable_v<RangeSizeT, ImproperlyDisabledMember&>);
221221
static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledMember&>);
222-
static_assert(!std::is_invocable_v<RangeSizeT, ImproperlyDisabledFunction&>);
222+
static_assert(std::is_invocable_v<RangeSizeT,
223+
ImproperlyDisabledFunction&>); // Ill-formed before P2602R2 Poison Pills are Too Toxic
223224
static_assert( std::is_invocable_v<RangeSizeT, const ImproperlyDisabledFunction&>);
224225

225226
// No begin end.

0 commit comments

Comments
 (0)