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

Fix handling of array rvalues for ranges::cbegin and its friends #3316

Merged

Conversation

frederick-vs-ja
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja commented Dec 31, 2022

When the argument is an rvalue of an array, ranges::cbegin, ranges::cend, ranges::crbegin, and ranges::crend should reject it with substitution failures, despite of whether the element type is complete or not. I think such requirements haven't been changed by P2278R4 (i.e. unchanged between C++20 and C++23).

(On the other hand, if the argument is an lvalue of an array of an incomplete element type, the program is ill-formed, no diagnostic required.)

I originally discovered the bug of implementation in #3187 (comment), but hadn't determined how to fix it at that time.


Clang 15 is buggy - it fails to perform shortcut in concept substitution when using requires-clause. This is probably LLVM-55945 and fixed in Clang 16 (Godbolt link).

The current workaround is combining constraints into one concept and using the abbreviated syntax.

@frederick-vs-ja frederick-vs-ja requested a review from a team as a code owner December 31, 2022 17:51
@strega-nil-ms
Copy link
Contributor

strega-nil-ms commented Jan 3, 2023

I'm not sure about this; the standard says (for cbegin for example, but for the rest too):

If E is an rvalue and enable_­borrowed_­range<remove_­cv_­t<T>> is false, ranges​::​cbegin(E) is ill-formed. ([range.access.cbegin]/1.1)

They are also missing the very important Note 1 from ranges::begin (and also ranges::{end, rbegin, rend, size, empty}):

[Note 1: Diagnosable ill-formed cases above result in substitution failure when ranges​::begin(E) appears in the immediate context of a template instantiation. — end note] ([range.access.begin]/3)

What this says to me is that ranges::cbegin(T &&) (and the like) should be ill-formed (not a substitution failure) for all T that don't satisfy enable_borrowed_range<T>.

@strega-nil-ms strega-nil-ms added the decision needed We need to choose something before working on this label Jan 3, 2023
@StephanTLavavej
Copy link
Member

We talked about this at the weekly maintainer meeting, and concluded that when WG21-P2278R4 updated the Standard, the Note that appears for ranges::begin et al. should have been applied to ranges::cbegin et al., but the Note is (by definition) informative (i.e. non-normative), so the mandated behavior is the same for all of them. Therefore the diagnosable ill-formed cases do indeed result in substitution failure.

@strega-nil-ms has volunteered to submit a editorial issue (or PR) to the C++ draft. Thanks Nicole!

@StephanTLavavej StephanTLavavej added bug Something isn't working ranges C++20/23 ranges and removed decision needed We need to choose something before working on this labels Jan 4, 2023
@strega-nil-ms
Copy link
Contributor

Submitted Draft-PR-6046.

Copy link
Contributor

@strega-nil-ms strega-nil-ms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the bug-fix!

stl/inc/xutility Outdated Show resolved Hide resolved
stl/inc/xutility Show resolved Hide resolved
Copy link
Contributor

@strega-nil-ms strega-nil-ms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Comment on lines +2967 to 2968
noexcept(noexcept(_RANGES data(_RANGES _Possibly_const_range(_Val)))) {
return _RANGES _As_const_pointer(_RANGES data(_RANGES _Possibly_const_range(_Val)));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change requested: I observe that the noexcept expression differs from the return expression because _As_const_pointer is unconditionally noexcept - this is a reasonable shortcut for throughput.

@StephanTLavavej StephanTLavavej self-assigned this Jan 11, 2023
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit a981f1e into microsoft:main Jan 12, 2023
@StephanTLavavej
Copy link
Member

Thanks again for finding and fixing this, so the implementations are consistent! 😻 🔍 ✅

@frederick-vs-ja frederick-vs-ja deleted the cpo-incomplete-array-rvalue branch January 12, 2023 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ranges C++20/23 ranges
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
  翻译: