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

Improve the __is_derived_from_optional concept #63530

Closed
mordante opened this issue Jun 26, 2023 · 6 comments
Closed

Improve the __is_derived_from_optional concept #63530

mordante opened this issue Jun 26, 2023 · 6 comments
Assignees
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@mordante
Copy link
Member

mordante commented Jun 26, 2023

Tested with
Clang version 17.0.0 (++20230624042319+ee2bf319bc05-1~exp1~20230624042420.1017)

The issue looks similar to #62943 but that fix is this version of Clang. Testing this code with libc++'s std module

import std;
  
int main(int, char**) {
  int t{3};
  std::optional<int> op{3};
  return op <=> t;
}

Gives the following compiler output

libcxx/test/std/utilities/optional/optional.comp_with_t/compare.three_way.pass.cpp:6:13: error: use of overloaded operator '<=>' is ambiguous (with operand types 'std::optional<int>' and 'int')
    6 |   return op <=> t;
      |          ~~ ^   ~
/llvm/build/generic-module-std-cxx23/include/c++/v1/optional:1612:1: note: candidate function [with _Tp = int, _Up = int]
 1612 | operator<=>(const optional<_Tp>& __x, const _Up& __v) {
      | ^
/llvm/build/generic-module-std-cxx23/include/c++/v1/optional:1612:1: note: candidate function [with _Tp = int, _Up = int]
 1612 | operator<=>(const optional<_Tp>& __x, const _Up& __v) {
      | ^
/llvm/build/generic-module-std-cxx23/include/c++/v1/optional:1612:1: note: candidate function [with _Tp = int, _Up = int]
 1612 | operator<=>(const optional<_Tp>& __x, const _Up& __v) {
      | ^
/llvm/build/generic-module-std-cxx23/include/c++/v1/optional:1612:1: note: candidate function [with _Tp = int, _Up = int]
 1612 | operator<=>(const optional<_Tp>& __x, const _Up& __v) {
      | ^
/llvm/build/generic-module-std-cxx23/include/c++/v1/optional:1612:1: note: candidate function [with _Tp = int, _Up = int]
 1612 | operator<=>(const optional<_Tp>& __x, const _Up& __v) {
      | ^
1 error generated.

error: command failed with exit status: 1

This is a manual reduction of the file libcxx/test/std/utilities/optional/optional.comp_with_t/compare.three_way.pass.cpp

@mordante mordante added the clang:modules C++20 modules and Clang Header Modules label Jun 26, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Jun 26, 2023

@llvm/issue-subscribers-clang-modules

@ChuanqiXu9
Copy link
Member

Note that the original reproducer is invalid without modules: https://godbolt.org/z/5aojvWcYW

@ChuanqiXu9
Copy link
Member

It turns out the reason for the issue is the same with that we don't merge the lambdas in modules well:

template <class _Tp>
concept __is_derived_from_optional = requires(const _Tp& __t) { []<class __Up>(const optional<__Up>&) {}(__t); };

If we change the implementation of __is_derived_from_optional to std::is_base_of (or other similar intrinsics), the behavior of the reproducer is expected.

Also personally I feel it looks better to use std::is_base_of (or other similar intrinsics) instead of relying on the lambda tricks even without modules, since std::is_base_of (or other similar intrinsics) uses the compiler built-in intrinsics to do this. It should be more efficient.

@mordante
Copy link
Member Author

Thanks, it seems I was a bit to aggressive removing code, https://godbolt.org/z/h5MxnxhYT works without modules and looks more like the original code.

Thanks for finding the issue. I will investigate whether we can indeed use std::is_base_of instead of this way. I first like to understand why we do it like this. I prefer the type_trait too, not only from an efficiency point of view, but also from a readability point of view.

I'll assign this to myself to keep track of it.

@mordante mordante assigned mordante and unassigned ChuanqiXu9 Jun 27, 2023
@mordante mordante added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. and removed clang:modules C++20 modules and Clang Header Modules labels Jun 27, 2023
@mordante mordante changed the title [C++20][Modules] incorrect error regarding ambiguous overloaded operator Improve the __is_derived_from_optional concept Jun 27, 2023
@ChuanqiXu9
Copy link
Member

BTW, I'll track the issue in the compiler side in #63544

@mordante
Copy link
Member Author

mordante commented Jul 1, 2023

I had a look and both is_base_of and derived_from take two template arguments. This one takes one argument and deduces the second argument. The trait also matches the wording in the Standard. So I guess it's not trivial to write this differently. Since there is already a patch for Clang I prefer to close this issue and wait for proper Clang support.

@mordante mordante closed this as completed Jul 1, 2023
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

No branches or pull requests

3 participants