https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97120
Bug ID: 97120 Summary: circular concept loops in <ranges> Product: gcc Version: 10.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: a...@cloudius-systems.com Target Milestone: --- The following example compiles with gcc and fails with clang. I believe clang is correct but can't prove it. ======= begin example ============= #include <ranges> void foo() { std::ranges::iota_view iota(2, 10); iota.begin(); } ======== end example ============== Clang complains that iota_view doesn't have a begin() member (which it does). I think the reason is that the constraint is evaluated before iota_view is fully defined. gcc evaluates lazily so it doesn't stumble on the problem. The circular chain is: 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. view_interface instantiates iterator_t, which is an alias to std::__detail::__range_iter_t. __range_iter_t instantiates __ranges_begin. __ranges_begin requires that its template parameter is a __member_begin<> (among other options, but this is the valid one here). __member_begin requires that the type (iota_view) have a begin() function. But the type isn't defined yet. I believe clang is correct, mostly because I believe concept evaluation should be eager and not lazy, not because I know it for a fact. Apologies for posting a clang issue here, I wouldn't if gcc could get asan+coroutines working. The problem will hit gcc if it implements eager evaluation too.