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

evaluation of constraints for std::ranges::views::drop() fails unnecessarily #46853

Closed
avikivity mannequin opened this issue Sep 13, 2020 · 10 comments
Closed

evaluation of constraints for std::ranges::views::drop() fails unnecessarily #46853

avikivity mannequin opened this issue Sep 13, 2020 · 10 comments
Labels
bugzilla Issues migrated from bugzilla c++20 concepts C++20 concepts duplicate Resolved as duplicate

Comments

@avikivity
Copy link
Mannequin

avikivity mannequin commented Sep 13, 2020

Bugzilla Link 47509
Version trunk
OS Linux
CC @JohelEGP,@mmatrosov,@craffael,@zygoloid,@viccie30,@jwakely

Extended Description

The test program

==== begin test program ====

#include <vector>
#include <ranges>

void f(std::vector<int> vec) {
    for (auto& e : vec | std::ranges::views::drop(1)) {
    }
}

==== end test program ====

Does not compile on clang, either with libc++ or libstdc++, failing on some enormously complicated constraints. gcc accepts it.

@avikivity
Copy link
Mannequin Author

avikivity mannequin commented Sep 20, 2020

I narrowed it down to eager evaluation of constraints:

  1. view_interface<iota_view> is instantiated as a base class of iota_view. Clearly iota_view isn't defined at this stage, it's just a forward-declared name.

  2. view_interface instantiates iterator_t, which is an alias to std::__detail::__range_iter_t.

  3. __range_iter_t instantiates __ranges_begin.

  4. __ranges_begin requires that its template parameter is a __member_begin<> (among other options, but this is the valid one here).

  5. __member_begin requires that the type (iota_view) have a begin() function. But the type isn't defined yet.

According to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97120#c1, evaluation should be lazy.

@llvmbot
Copy link
Member

llvmbot commented Sep 21, 2020

This reduces to something interesting:

Clang accepts:

template <typename _Tp>
concept __member_begin = requires(_Tp __t) {
    {__t.begin()};
};
template <typename _Tp>
concept nothing = requires(_Tp __t) {
    {42};
};
template <typename _Tp>
requires __member_begin<_Tp> void __ranges_begin() {}
template <typename _Derived>
struct view_interface {
    void foo() requires __member_begin<_Derived> {}
//    void bar() requires nothing<decltype(__ranges_begin<_Derived>())> {}
};
struct drop_view : public view_interface<drop_view> {};

Uncomment the declaration of bar and clang rejects this. gcc is OK with both.

If I understand it correctly, both gcc and clang agree that the direct use of a unsatisfied requires should just disable foo. The disagreement is about an indirect one, like in bar(). With gcc bar() is just disabled, but clang produces an error. Note that gcc rejects:


template <typename _Tp>
concept __member_begin = requires(_Tp __t) {
    {__t.begin()};
};
template <typename _Tp>
concept nothing = requires(_Tp __t) {
    {42};
};
template <typename _Tp>
requires __member_begin<_Tp> void __ranges_begin() {}
template <typename _Derived>
struct view_interface {
    void foo() requires __member_begin<_Derived> {}
    void bar() requires nothing<decltype(__ranges_begin<_Derived>())> {}
};
struct drop_view : public view_interface<drop_view> {
    void zed() {
        this->bar();
    }
};

@mmatrosov
Copy link

mmatrosov commented Jun 25, 2021

This is indeed clang's bug: #50208

@jwakely
Copy link
Mannequin

jwakely mannequin commented Nov 23, 2021

This is indeed clang's bug: llvm/llvm-bugzilla-archive#50864

And this one and that are both dups of #44178

@Craffael
Copy link
Mannequin

Craffael mannequin commented Nov 27, 2021

mentioned in issue #48855

@ldionne
Copy link
Member

ldionne commented Dec 14, 2021

This doesn't happen anymore, see https://godbolt.org/z/5fhnM3YTo.

Also, on libc++, we haven't implemented views::drop yet (I have a patch locally and I need to finish it up) so this fails as expected. But the Clang bug seems to be gone.

@ldionne ldionne closed this as completed Dec 14, 2021
@avikivity
Copy link
Contributor

It does not compile with clang trunk: https://godbolt.org/z/Prn9Kze64

@ldionne
Copy link
Member

ldionne commented Dec 15, 2021

Oh yes, you are right, sorry about that.

https://godbolt.org/z/hsvoWM3je shows:

Clang trunk / libstdc++: fails
GCC trunk / libstdc++: works
Clang trunk / libc++: fails because libc++ doesn't implement it yet

@ldionne ldionne reopened this Dec 15, 2021
@jwakely
Copy link
Contributor

jwakely commented Jan 11, 2022

And this one and that are both dups of Bug 44833

Which is now #44178

@Quuxplusone Quuxplusone added the concepts C++20 concepts label Jan 16, 2022
@Quuxplusone
Copy link
Contributor

Duplicate of #44178.

@Quuxplusone Quuxplusone added the duplicate Resolved as duplicate label Jan 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla c++20 concepts C++20 concepts duplicate Resolved as duplicate
Projects
Status: No status
Development

No branches or pull requests

6 participants