This is an archive of the discontinued LLVM Phabricator instance.

[libc++][NFCI] span: replace enable_if with concepts
ClosedPublic

Authored by Mordante on Sep 2 2021, 9:24 PM.

Details

Reviewers
ldionne
Quuxplusone
philnik
var-const
EricWF
jloser
Group Reviewers
Restricted Project
Summary

Several span constructors use enable_if which is verbose. Replace these with
concepts or requires expressions.

Diff Detail

Event Timeline

jloser requested review of this revision.Sep 2 2021, 9:24 PM
jloser created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptSep 2 2021, 9:24 PM
Herald added a reviewer: Restricted Project. · View Herald Transcript

Thanks for working on this! In general I prefer concepts over enable_ifs. Unfortunately some of our supported compilers don't have proper concepts support yet. We could use #ifs to guard against that, however IMO that would make the code unneeded ugly. Alternatively we wait until we only support compilers with concepts support.

@ldionne Do you know when AppleClang 13 will be released and whether it has concepts support?

(I want to discuss this before doing a review.)

Quuxplusone added inline comments.Sep 3 2021, 6:17 AM
libcxx/include/span
237

enable_if_t which is verbose and slow

I benchmarked enable_if_t versus _EnableIf versus requires over at https://reviews.llvm.org/D108216#inline-1037983 a couple days ago, and it seemed that requires was about 20% slower than enable_if_t/_EnableIf. What evidence led you to the "and slow" part of your comment?

jloser updated this revision to Diff 370580.Sep 3 2021, 7:31 AM
jloser retitled this revision from [libc++] span: replace enable_if with requires. NFCI. to [libc++][NFCI] span: replace enable_if with requires.
jloser edited the summary of this revision. (Show Details)

Tone down wording in commit message with regard to speed of enable_if_t vs requires

jloser added inline comments.Sep 3 2021, 7:36 AM
libcxx/include/span
237

Sorry, I was a bit aggressive/strong in my commit wording here: I've adjusted that now. I have not benchmarked enable_if_t vs requires in this commit, so I've omitted the speed remark.

It surprises me a bit that requires is that much slower. I'd be interested to see an extension of your benchmark to account for enable_if_t when used as a default template parameter (e.g. does the number of templates make things go "really bad" after some threshold?).

jloser marked an inline comment as done.Sep 3 2021, 7:36 AM
jloser added a comment.Sep 3 2021, 7:38 AM

Thanks for working on this! In general I prefer concepts over enable_ifs. Unfortunately some of our supported compilers don't have proper concepts support yet. We could use #ifs to guard against that, however IMO that would make the code unneeded ugly. Alternatively we wait until we only support compilers with concepts support.

@ldionne Do you know when AppleClang 13 will be released and whether it has concepts support?

(I want to discuss this before doing a review.)

Thanks for some context. I started poking around in span last night as I came across this recent libc++ bug. It made me realize there are several missing constraints for span, which motivated a move to requires clauses first to make things not as verbose in fixing all of the constraints.

ldionne requested changes to this revision.Sep 3 2021, 11:05 AM

Thanks for working on this! In general I prefer concepts over enable_ifs. Unfortunately some of our supported compilers don't have proper concepts support yet. We could use #ifs to guard against that, however IMO that would make the code unneeded ugly. Alternatively we wait until we only support compilers with concepts support.

@ldionne Do you know when AppleClang 13 will be released and whether it has concepts support?

(I want to discuss this before doing a review.)

Thanks for some context. I started poking around in span last night as I came across this recent libc++ bug. It made me realize there are several missing constraints for span, which motivated a move to requires clauses first to make things not as verbose in fixing all of the constraints.

Thanks a lot for your interest in fixing this. Since we have been shipping std::span and we do support compilers that don't implement concepts yet, I'd like to push back against this change *for the time being*.

What I suggest is that you implement the changes discussed in https://bugs.llvm.org/show_bug.cgi?id=51443 using enable_if_t, and then we revisit this change as soon as all supported compilers implement concepts, which should be the case within a couple months. When that's the case, this patch will have all my support. Does that seem reasonable?

This revision now requires changes to proceed.Sep 3 2021, 11:05 AM

Thanks for working on this! In general I prefer concepts over enable_ifs. Unfortunately some of our supported compilers don't have proper concepts support yet. We could use #ifs to guard against that, however IMO that would make the code unneeded ugly. Alternatively we wait until we only support compilers with concepts support.

@ldionne Do you know when AppleClang 13 will be released and whether it has concepts support?

(I want to discuss this before doing a review.)

Thanks for some context. I started poking around in span last night as I came across this recent libc++ bug. It made me realize there are several missing constraints for span, which motivated a move to requires clauses first to make things not as verbose in fixing all of the constraints.

Thanks a lot for your interest in fixing this. Since we have been shipping std::span and we do support compilers that don't implement concepts yet, I'd like to push back against this change *for the time being*.

What I suggest is that you implement the changes discussed in https://bugs.llvm.org/show_bug.cgi?id=51443 using enable_if_t, and then we revisit this change as soon as all supported compilers implement concepts, which should be the case within a couple months. When that's the case, this patch will have all my support. Does that seem reasonable?

Seems very reasonable and what I'd recommend as well. I'll move forward with implementing http://wg21.link/p1394 using enable_if_t and as a follow-up I'll dig into the paper for the conditional explicitness of the constructors as talked about in the bug. We'll revisit this patch once we drop support for compilers that don't support concepts.

jloser added inline comments.Oct 11 2021, 1:58 PM
libcxx/include/span
237

@Quuxplusone @ldionne how do you feel about revisiting this PR now that concepts should be fine to use in <span>?

As it stands, we have a mix of enable_if_t vs concepts in some C++20 code in libc++ -- with most of the C++20-code being concepts and <span> being some of the former.

libcxx/include/span
237

We're still testing buildkite configurations (on Apple targets) where libcpp-no-concepts is a thing. IMO it will be appropriate to migrate things to Concepts only after someone lands a patch removing libcpp-no-concepts from the tests and _LIBCPP_HAS_NO_CONCEPTS from the code.
(Otherwise, we'll be regressing those platforms — it'll be OK to use <span> on those platforms in 2021, but not OK to use <span> on those platforms in 2022. Also, if you do these steps out of order, the <span> step will just physically be bigger, because you'll have to manually UNSUPPORTED: libcpp-no-concepts all of its tests.)

If your hypothesis is that "by the time Clang 15 ships, these platforms will have Concepts support," then ok cool, make a PR to remove libcpp-no-concepts and see if people agree about that; then let's revisit this after that lands. :)

@ldionne @Mordante now that all of our supported compilers support concepts, we can revisit this patch. What's your general appetite for using concepts (here and elsewhere for C++20-or-later code)? I prefer concepts, but I think Arthur had a benchmark showing enable_if was quicker to compile IIRC.

Herald added a project: Restricted Project. · View Herald TranscriptMar 14 2022, 6:24 PM
Mordante requested changes to this revision.Mar 15 2022, 12:09 AM

@ldionne @Mordante now that all of our supported compilers support concepts, we can revisit this patch. What's your general appetite for using concepts (here and elsewhere for C++20-or-later code)? I prefer concepts, but I think Arthur had a benchmark showing enable_if was quicker to compile IIRC.

Thanks for bringing this up again!

Arthur indeed had a benchmark concepts were slower. If easily done it would be nice to run this benchmark again. Compiler writers had years to optimize SFINAE, but concepts are fairly new. So I expect compiler writers to improve the speed processing concepts for the next years.

From a readability and maintainability point of view I prefer concepts.

… then we revisit this change as soon as all supported compilers implement concepts, which should be the case within a couple months. When that's the case, this patch will have all my support.

Based on this comment I started reviewing, but the patch needs a rebase before reviewing. Feel free to wait until @ldionne agrees that we still want this improvement.

libcxx/include/span
467–468

These spaces look odd.

468

I was wondering why not using __is_span_compatible_container_v<_Container, _Tp>, but it seems __is_span_compatible_container no longer exists. So I stopped reviewing here. When we want to use this patch it needs to be rebased first.

I would support exploring this -- unless enable_if is significantly faster, I think we should go for the readability and diagnostics improvement.

jloser updated this revision to Diff 436177.Jun 11 2022, 7:07 PM

Rebase, apply concepts everywhere.

jloser retitled this revision from [libc++][NFCI] span: replace enable_if with requires to [libc++][NFCI] span: replace enable_if with concepts.Jun 11 2022, 7:08 PM
jloser edited the summary of this revision. (Show Details)
jloser updated this revision to Diff 436178.Jun 11 2022, 7:09 PM

Fix spacing in template id list

jloser marked 3 inline comments as done.Jun 11 2022, 7:21 PM
philnik added inline comments.Jun 12 2022, 2:53 AM
libcxx/include/span
209

Could you rename this to __span_compatible_sentinel_for to keep the naming scheme of sized_sentinel_for and friends?

454–455

Wouldn't that also work?

479–480

Same here.

608

Is there a reason we don't just use decltype(auto) as the return type and drop the trailing return type completely?

jloser updated this revision to Diff 436238.Jun 12 2022, 11:01 AM
jloser marked 4 inline comments as done.

Address philnik's comments

libcxx/include/span
454–455

Yes, it works, but loses the symmetry with the next function template below (constrained by __span_array_convertible<const _OtherElementType, element_type>). I originally had it as you suggested. I'll make that change and we can let others decide which they prefer; I have a slight preference towards what you suggested because it's terser.

608

No reason. Just switched to decltype(auto) since we have existing use of that in variant, and some of ranges, etc.

ldionne accepted this revision.Jun 14 2022, 12:52 PM

LGTM with comment.

libcxx/include/span
608

I think it's actually confusing to use decltype(auto) here since it suggests that there's some value-category preservation going on, when there really is none. I would just use auto instead.

Just landed this with cb48ed38b8d09ef9cfa1f7258342d0379f169074. I accidentally did it from a different branch, so this review didn't auto-close. Sorry about that. Can someone elaborate on how to manually close this review? The docs at https://llvm.org/docs/Phabricator.html seem to suggest there's a Close Revision button, but I'm not seeing it.

Just landed this with cb48ed38b8d09ef9cfa1f7258342d0379f169074. I accidentally did it from a different branch, so this review didn't auto-close. Sorry about that. Can someone elaborate on how to manually close this review? The docs at https://llvm.org/docs/Phabricator.html seem to suggest there's a Close Revision button, but I'm not seeing it.

When you submit a comment there's an Add Action... drop down, there you can close the revision.

Mordante commandeered this revision.Jun 16 2022, 8:44 AM
Mordante edited reviewers, added: jloser; removed: Mordante.

Commandeer to close it.

This revision is now accepted and ready to land.Jun 16 2022, 8:44 AM
Mordante closed this revision.Jun 16 2022, 8:45 AM

As mentioned the commit was landed, but from the wrong branch so it wasn't closed automatically.