https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99599
Bug ID: 99599 Summary: Concepts requirement falsely reporting recursion, breaks tag_invoke pattern Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: the_gamester28 at msn dot com Target Milestone: --- The following code compiles fine on GCC 10, Clang, MSVC, but fails in GCC 11/trunk: ### begin struct foo_tag{}; struct bar_tag{}; template <class T> concept fooable = requires(T it) { invoke_tag(foo_tag{}, it); // <-- here }; template<class T> auto invoke_tag(foo_tag, T in) { return in; } template<fooable T> auto invoke_tag(bar_tag, T it) { return it; } int main() { // Neither line below compiles in GCC 11, independently of the other return invoke_tag(foo_tag{}, 2); return invoke_tag(bar_tag{}, 2); } ### end Produces the following compiler error: ### begin <source>: In substitution of 'template<class T> requires fooable<T> auto invoke_tag(bar_tag, T) [with T = int]': <source>:6:15: required by substitution of 'template<class T> requires fooable<T> auto invoke_tag(bar_tag, T) [with T = int]' <source>:21:35: required from here <source>:5:9: required for the satisfaction of 'fooable<T>' [with T = int] <source>:5:19: in requirements with 'T it' [with T = int] <source>:5:19: error: satisfaction of atomic constraint 'requires(T it) {invoke_tag({}, it);} [with T = T]' depends on itself 5 | concept fooable = requires(T it) { | ^~~~~~~~~~~~~~~~ 6 | invoke_tag(foo_tag{}, it); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 | }; | ~ ### end It seems that the template requirements of invoke_tag(bar_tag, int) are considered while evaluating line marked "here". Requirements of irrelevant overloads should not be considered, as it can potentially lead to falsely reporting a cyclic dependency. This bug effectively prevents using the modern tag_invoke pattern, which is increasingly used as a customisation point in many modern libraries.