Skip to content

Commit 3891468

Browse files
ZERO-Nldionne
andauthored
[libc++] Avoid using **this in error messages for expected monadic operations (#84840)
Instead of using **this in error messages for std::expected monadic operations, use value(). As shown in LWG3969, **this can trigger unintended ADL and while it's only an error message, we might as well be ADL-correct there too. Co-authored-by: Louis Dionne <[email protected]>
1 parent beecf2c commit 3891468

File tree

2 files changed

+20
-20
lines changed

2 files changed

+20
-20
lines changed

libcxx/include/__expected/expected.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -918,9 +918,9 @@ class expected : private __expected_base<_Tp, _Err> {
918918
requires is_constructible_v<_Err, _Err&>
919919
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
920920
using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
921-
static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
921+
static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected");
922922
static_assert(is_same_v<typename _Up::error_type, _Err>,
923-
"The result of f(**this) must have the same error_type as this expected");
923+
"The result of f(value()) must have the same error_type as this expected");
924924
if (has_value()) {
925925
return std::invoke(std::forward<_Func>(__f), this->__val());
926926
}
@@ -931,9 +931,9 @@ class expected : private __expected_base<_Tp, _Err> {
931931
requires is_constructible_v<_Err, const _Err&>
932932
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
933933
using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>;
934-
static_assert(__is_std_expected<_Up>::value, "The result of f(**this) must be a specialization of std::expected");
934+
static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected");
935935
static_assert(is_same_v<typename _Up::error_type, _Err>,
936-
"The result of f(**this) must have the same error_type as this expected");
936+
"The result of f(value()) must have the same error_type as this expected");
937937
if (has_value()) {
938938
return std::invoke(std::forward<_Func>(__f), this->__val());
939939
}
@@ -945,9 +945,9 @@ class expected : private __expected_base<_Tp, _Err> {
945945
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
946946
using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>;
947947
static_assert(
948-
__is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
948+
__is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected");
949949
static_assert(is_same_v<typename _Up::error_type, _Err>,
950-
"The result of f(std::move(**this)) must have the same error_type as this expected");
950+
"The result of f(std::move(value())) must have the same error_type as this expected");
951951
if (has_value()) {
952952
return std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
953953
}
@@ -959,9 +959,9 @@ class expected : private __expected_base<_Tp, _Err> {
959959
_LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
960960
using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>;
961961
static_assert(
962-
__is_std_expected<_Up>::value, "The result of f(std::move(**this)) must be a specialization of std::expected");
962+
__is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected");
963963
static_assert(is_same_v<typename _Up::error_type, _Err>,
964-
"The result of f(std::move(**this)) must have the same error_type as this expected");
964+
"The result of f(std::move(value())) must have the same error_type as this expected");
965965
if (has_value()) {
966966
return std::invoke(std::forward<_Func>(__f), std::move(this->__val()));
967967
}

libcxx/test/libcxx/utilities/expected/expected.expected/and_then.mandates.verify.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@
1111
// Test the mandates
1212
// template<class F> constexpr auto and_then(F&& f) &;
1313
// Mandates:
14-
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(**this)>>
14+
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(value())>>
1515
// U is a specialization of std::expected and std::is_same_v<U:error_type, E> is true
1616

1717
// template<class F> constexpr auto and_then(F&& f) const &;
1818
// Mandates:
19-
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(**this)>>
19+
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(value())>>
2020
// U is a specialization of std::expected and std::is_same_v<U:error_type, E> is true
2121

2222
// template<class F> constexpr auto and_then(F&& f) &&;
2323
// Mandates:
24-
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(**this)>>
24+
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(value())>>
2525
// U is a specialization of std::expected and std::is_same_v<U:error_type, E> is true
2626

2727
// template<class F> constexpr auto and_then(F&& f) const &&;
2828
// Mandates:
29-
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(**this)>>
29+
// Let U be std::remove_cvref_t<std::invoke_result<F, decltype(value())>>
3030
// U is a specialization of std::expected and std::is_same_v<U:error_type, E> is true
3131

3232
#include <expected>
@@ -52,7 +52,7 @@ void test() {
5252
{
5353
std::expected<int, int> f1(1);
5454
f1.and_then(lval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &)>' requested here}}
55-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(**this) must be a specialization of std::expected}}
55+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must be a specialization of std::expected}}
5656
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
5757
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
5858
}
@@ -61,7 +61,7 @@ void test() {
6161
{
6262
std::expected<int, int> f1(1);
6363
f1.and_then(lval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &)>' requested here}}
64-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(**this) must have the same error_type as this expected}}
64+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must have the same error_type as this expected}}
6565
}
6666
}
6767

@@ -71,7 +71,7 @@ void test() {
7171
{
7272
const std::expected<int, int> f1(1);
7373
f1.and_then(clval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &)>' requested here}}
74-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(**this) must be a specialization of std::expected}}
74+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must be a specialization of std::expected}}
7575
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
7676
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
7777
}
@@ -80,7 +80,7 @@ void test() {
8080
{
8181
const std::expected<int, int> f1(1);
8282
f1.and_then(clval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &)>' requested here}}
83-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(**this) must have the same error_type as this expected}}
83+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must have the same error_type as this expected}}
8484

8585
}
8686
}
@@ -91,7 +91,7 @@ void test() {
9191
{
9292
std::expected<int, int> f1(1);
9393
std::move(f1).and_then(rval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(int &&)>' requested here}}
94-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(**this)) must be a specialization of std::expected}}
94+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must be a specialization of std::expected}}
9595
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
9696
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
9797
}
@@ -100,7 +100,7 @@ void test() {
100100
{
101101
std::expected<int, int> f1(1);
102102
std::move(f1).and_then(rval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(int &&)>' requested here}}
103-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(**this)) must have the same error_type as this expected}}
103+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must have the same error_type as this expected}}
104104
}
105105
}
106106

@@ -110,7 +110,7 @@ void test() {
110110
{
111111
const std::expected<int, int> f1(1);
112112
std::move(f1).and_then(crval_return_not_std_expected); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<int (&)(const int &&)>' requested here}}
113-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(**this)) must be a specialization of std::expected}}
113+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must be a specialization of std::expected}}
114114
// expected-error-re@*:* {{{{.*}}cannot be used prior to '::' because it has no members}}
115115
// expected-error-re@*:* {{no matching constructor for initialization of{{.*}}}}
116116
}
@@ -119,7 +119,7 @@ void test() {
119119
{
120120
const std::expected<int, int> f1(1);
121121
std::move(f1).and_then(crval_error_type_not_same_as_int); // expected-note{{in instantiation of function template specialization 'std::expected<int, int>::and_then<std::expected<int, NotSameAsInt> (&)(const int &&)>' requested here}}
122-
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(**this)) must have the same error_type as this expected}}
122+
// expected-error-re@*:* {{static assertion failed {{.*}}The result of f(std::move(value())) must have the same error_type as this expected}}
123123
}
124124
}
125125
}

0 commit comments

Comments
 (0)