Skip to content
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

[libc++] Fix unexpected heterogeneous comparison #115249

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

frederick-vs-ja
Copy link
Contributor

Currently, libc++ incorrectly rejects heterogeneous comparison of unexpected, because the operator== is only a hidden friend of unexpected<_Err> but not of unexpected<_Err2>. We need to call the error() member function on __y.

Originally discovered by @Quuxplusone. Fixes Quuxplusone#40.

@frederick-vs-ja frederick-vs-ja requested a review from a team as a code owner November 7, 2024 02:14
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Nov 7, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 7, 2024

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

Changes

Currently, libc++ incorrectly rejects heterogeneous comparison of unexpected, because the operator== is only a hidden friend of unexpected&lt;_Err&gt; but not of unexpected&lt;_Err2&gt;. We need to call the error() member function on __y.

Originally discovered by @Quuxplusone. Fixes Quuxplusone/llvm-project#40.


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

2 Files Affected:

  • (modified) libcxx/include/__expected/unexpected.h (+1-1)
  • (modified) libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp (+13)
diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h
index c7fe3c52e43114..cf110bcf69a827 100644
--- a/libcxx/include/__expected/unexpected.h
+++ b/libcxx/include/__expected/unexpected.h
@@ -108,7 +108,7 @@ class unexpected {
 
   template <class _Err2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) {
-    return __x.__unex_ == __y.__unex_;
+    return __x.__unex_ == __y.error();
   }
 
 private:
diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
index 3c29cf97580460..7098ffc22c5dab 100644
--- a/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
@@ -23,15 +23,28 @@
 struct Error{
   int i;
   friend constexpr bool operator==(const Error&, const Error&) = default;
+  friend constexpr bool operator==(const Error& lhs, int rhs) noexcept {
+    return lhs.i == rhs;
+  }
 };
 
 constexpr bool test() {
   std::unexpected<Error> unex1(Error{2});
   std::unexpected<Error> unex2(Error{3});
   std::unexpected<Error> unex3(Error{2});
+
   assert(unex1 == unex3);
   assert(unex1 != unex2);
   assert(unex2 != unex3);
+
+  std::unexpected<int> unex_i1(1);
+  std::unexpected<int> unex_i2(2);
+
+  assert(unex1 != unex_i1);
+  assert(unex_i1 != unex1);
+  assert(unex1 == unex_i2);
+  assert(unex_i2 == unex1);
+
   return true;
 }
 

Copy link

github-actions bot commented Nov 7, 2024

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

Currently, libc++ incorrectly rejects heterogeneous comparison of
`unexpected`, because the `operator==` is only a hidden friend of
`unexpected<_Err>` but not of `unexpected<_Err2>`. We need to call the
`error()` member function on `__y`.
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.

Error on unexpected(1) == unexpected(1L)
2 participants