This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Work around a Clang bug in transform_view, and regression-test.
ClosedPublic

Authored by Quuxplusone on Dec 5 2021, 7:28 AM.

Details

Summary

Clang trunk rejects the new test case, but this is a Clang bug (PR47414, 47509, 50864, 44833).

In module 'std' imported from /Users/aodwyer/llvm-project/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp:17:
/Users/aodwyer/llvm-project/build2/include/c++/v1/__ranges/transform_view.h:85:44: error: constraints not satisfied for alias template 'range_reference_t' [with _Rp = const NonConstView]
             regular_invocable<const _Fn&, range_reference_t<const _View>>
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/aodwyer/llvm-project/build2/include/c++/v1/__ranges/transform_view.h:416:25: note: in instantiation of template class 'std::ranges::transform_view<NonConstView, (lambda at /Users/aodwyer/llvm-project/libcxx/test/std/ranges/range.adaptors/range.transform/general.pass.cpp:73:71)>' requested here
      -> decltype(      transform_view(_VSTD::forward<_Range>(__range), _VSTD::forward<_Fn>(__f)))
                        ^

We can work around this by adding a layer of indirection: put the problematic constraint into a named concept and Clang becomes more amenable to SFINAE'ing instead of hard-erroring.

Drive-by simplify range.transform/general.pass.cpp to make it clearer what it's actually testing in this area.

Diff Detail

Event Timeline

Quuxplusone requested review of this revision.Dec 5 2021, 7:28 AM
Quuxplusone created this revision.
Herald added 1 blocking reviewer(s): Restricted Project. · View Herald TranscriptDec 5 2021, 7:28 AM
ldionne accepted this revision.Dec 6 2021, 7:01 AM

I bet you encountered this while working on views::drop & friends? I had the same issue and I had an unfinished patch to fix this locally - thanks for finishing up and sorry for the duplicate work.

This revision is now accepted and ready to land.Dec 6 2021, 7:01 AM

Yep, or rather, my goal was to get my local Clang+libc++ to compile some training-lab-exercise code like

bool isPalindromicByAuthor(std::ranges::bidirectional_range auto&& r) {
    return std::ranges::equal(
        r | std::views::transform(&Book::author),
        r | std::views::reverse | std::views::transform(&Book::author)
    );
}
~~~
assert(isPalindromicByAuthor(shelf | std::views::drop(1)));

This bug and take/drop were basically leaves of the same tree.