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

<optional>: Potential constraint recursion for operator<=>(const optional<T>&, const U&) #1674

Closed
CaseyCarter opened this issue Feb 22, 2021 · 3 comments · Fixed by #2011
Closed
Labels
fixed Something works now, yay! LWG issue needed A wording defect that should be submitted to LWG as a new issue spaceship C++20 operator <=>

Comments

@CaseyCarter
Copy link
Member

CaseyCarter commented Feb 22, 2021

While implementing <=> support for std::optional we stumbled across what appears to be constraint recursion for the operator<=> signature specified in [optional.comp.with.t]/25 when the second argument is a specialization of optional. Specifically, checking three_way_comparable_with seems to recurse via checking the constraint that e.g. < is viable for operator<(const optional<T>&, const optional<U>&), which it certainly is if <=> is provided by the first signature. We avoided the recursion by adding an additional constraint to the first signature requiring that U is not a specialization of optional, which is checked before the three_way_comparable_with constraint.

STL/stl/inc/optional

Lines 646 to 650 in 4c862ee

template <class _Ty1, class _Ty2>
requires (!_Is_specialization_v<_Ty2, optional>) // TRANSITION, GH-1674
&& three_way_comparable_with<_Ty1, _Ty2>
_NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2>
operator<=>(const optional<_Ty1>& _Left, const _Ty2& _Right) {

Looking at it now (with the workaround disabled) the recursion only manifests when compiling with Clang. Given how differently Clang and MSVC handle C++20 relational operator rewrites it's not clear to me if the constraint recursion is real or an artifact of said rewrites in Clang. We need to reduce this to something library-free and then determine whether the bug is in Clang or the C++ Standard and deal with it appropriately. (I will nonetheless tag this "LWG issue needed" for the time being.)

@CaseyCarter CaseyCarter added the LWG issue needed A wording defect that should be submitted to LWG as a new issue label Feb 22, 2021
@StephanTLavavej StephanTLavavej added the spaceship C++20 operator <=> label Feb 22, 2021
@jwakely
Copy link

jwakely commented Jun 7, 2021

I think this is a defect in the standard library. Libstdc++ is missing the three_way_comparable_with<U,T> constraint on operator<=>(const optional<T>&, const U&) but once I add it, GCC also hits this constraint recursion (and an ICE).

@CaseyCarter
Copy link
Member Author

CaseyCarter commented Jun 7, 2021

I've submitted an LWG issue for this defect - with our workaround as proposed resolution - and will report back here when LWGChair assigns an issue number. We can then change the // TRANSITION, GH-1674 comment to // LWG-XXXX and close this issue.

CaseyCarter added a commit to CaseyCarter/STL that referenced this issue Jun 14, 2021
@CaseyCarter
Copy link
Member Author

This is LWG-3566; #2011 updates the comment in <optional> to refer to the LWG issue and closes this issue.

StephanTLavavej pushed a commit that referenced this issue Jun 29, 2021
@StephanTLavavej StephanTLavavej added the fixed Something works now, yay! label Jun 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixed Something works now, yay! LWG issue needed A wording defect that should be submitted to LWG as a new issue spaceship C++20 operator <=>
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants