https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92268
Bug ID: 92268 Summary: Constraint normalization substitutes parameter too early Product: gcc Version: 10.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Blocks: 67491 Target Milestone: --- The following program fails to compile with -std=gnu++2a template<typename T, typename U> struct common_reference { }; template<typename T, typename U> using common_reference_t = typename common_reference<T, U>::type; template<typename T, typename U> concept foo = true; template<typename T, typename U> concept bar = true; template<typename T, typename U> concept baz = true; template<typename T, typename U> concept common_reference_with = foo<common_reference_t<T, U>, common_reference_t<U, T>> && bar<common_reference_t<T, U>, common_reference_t<U, T>> && baz<common_reference_t<T, U>, common_reference_t<U, T>>; template<typename T> using iter_reference_t = decltype(((T*)0)->f()); template<typename I> concept forward_iterator = common_reference_with<iter_reference_t<I>&&, typename I::value_type&>; struct test_range { struct iterator { using value_type = int; char f() const; }; iterator begin(); }; template<typename T> concept F = requires (T& t) { { t.begin() } -> forward_iterator; }; static_assert( !F<test_range> ); Checking the F<test_range> concept fails: bug.cc:37:33: error: no type named 'type' in 'struct common_reference<char&&, int&>' 37 | concept F = requires (T& t) { { t.begin() } -> forward_iterator; }; | ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ bug.cc:37:33: error: no type named 'type' in 'struct common_reference<char&&, int&>' bug.cc:37:33: error: no type named 'type' in 'struct common_reference<char&&, int&>' On IRC Jason said: [02:36] <jason> jwakely: you're hitting an error during normalization, which means the constraints could never be satisfied [02:40] <jason> but it looks like when we normalize the forward_iterator constraint on the compound-requirement we're normalizing forward_iterator<iterator>, which is wrong -- we should be normalizing forward_iterator<T>, and then checking whether that's satisfied with iterator [02:40] <jason> so it's a compiler bug [02:40] <jason> as well as the diagnostic issue [02:40] <jason> Andrew sent me a patch to improve handling of nested requirements that I haven't looked at yet, it may help with this Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67491 [Bug 67491] [meta-bug] concepts issues