See <https://wg21.link/P2963R3>.
Created attachment 58759 [details] gcc15-pr115746-wip.patch Untested WIP patch.
I'm afraid I'd appreciate some guidance, mainly with how to implement the satisfaction checking of fold expanded constraints. The way I've implemented it is that when testing its satisfaction, another argument with TREE_LIST of the packs and corresponding current index (which pack element is currently being tested for satisfaction) is passed, in sat_hasher::hash and sat_hasher::equal this is looked up and in tsubst_parameter_mapping too and if it sees a pack, it replaces it with the pack element. Now, this works fine for the easy testcases (concepts/variadic{2,4}.C, cpp26/fold-constr{1,2,4}.C), where in the atomic constraint mapping the template argument is used directly, but it doesn't work and causes ICE on the concepts/diagnostic3.C and cpp26/fold-constr3.C testcases; e.g. in diagnostic3.C, the fold expanded constraint notes it is a pack expansion of the Is pack, but in the mapping it uses S<Is> as the parameter. I also think cpp26/fold-constr5.C fails because of that (though, in there there is a mismatch between my expectations where I expect static_assert (bar <int> ()); to fail because C<typename U::type> && ... && C<typename T::type> should be normalized to (C<typename U::type> && ...) && C<typename T::type> where U is an empty pack, so (C<typename U::type> && ...) should be satisfied, but C<typename T::type> shouldn't be because int::type is invalid, and for conjunction I think that should then be unsatisfied, but clang++ trunk doesn't diagnose that one). In fold-constr6.C static_assert (U<int>::bar<int> ()); is rejected by clang++ trunk and I think in that case it shouldn't subsume but with my patch apparently it is accepted.
BTW, with a modified version of fold-constr5.C which doesn't involve any fold expanded constraints: struct A { using type = int; }; struct B { using type = long; }; template <class T> concept C = true; template <class T, class U> requires (C<typename U::type> && C<typename T::type>) // { dg-error "is not a class, struct, or union type" } constexpr bool bar () { return true; }; static_assert (bar <A, B> ()); static_assert (bar <int, int> ()); // { dg-error "no matching function for call" } static_assert (bar <B, long> ()); // { dg-error "no matching function for call" } static_assert (bar <unsigned, A> ()); // { dg-error "no matching function for call" } template <class T, class U> requires (C<typename T::type> && C<typename U::type>) // { dg-error "is not a class, struct, or union type" } constexpr bool baz () { return true; }; static_assert (baz <B, A> ()); static_assert (baz <int, long> ()); // { dg-error "no matching function for call" } static_assert (baz <B, long> ()); // { dg-error "no matching function for call" } static_assert (baz <unsigned, A> ()); // { dg-error "no matching function for call" } template <class T, class U> requires (C<typename U::type> || C<typename T::type>) // { dg-error "is not a class, struct, or union type" } constexpr bool corge () { return true; }; static_assert (corge <B, A> ()); static_assert (corge <int, int> ()); // { dg-error "no matching function for call" } static_assert (corge <B, long> ()); static_assert (corge <unsigned, A> ()); template <class T, class U> requires (C<typename T::type> || C<typename U::type>) // { dg-error "is not a class, struct, or union type" } constexpr bool garply () { return true; }; static_assert (garply <B, A> ()); static_assert (garply <int, int> ()); // { dg-error "no matching function for call" } static_assert (garply <B, long> ()); static_assert (garply <unsigned, A> ()); g++ accepts all of this without any errors (tried 10.1, 11.1, 12.1, 13.1, 14.1 and trunk), while clang++ rejects it at the dg-error lines; and my (sure, limited) understanding suggests that it should not be satisfied.
Created attachment 58763 [details] gcc15-pr115746-wip.patch Updated patch which handles satisfy_atom by modifying (a copy of) args instead of the old way, plus removes the pack tree from in between FOLD_CONSTR and the actual constraint. Sadly, this fixed only diagnostic3.C, but not the rest: FAIL: g++.dg/cpp26/fold-constr3.C -std=c++26 (internal compiler error: in dependent_type_p, at cp/pt.cc:28060) FAIL: g++.dg/cpp26/fold-constr3.C -std=c++26 (test for errors, line 10) FAIL: g++.dg/cpp26/fold-constr3.C -std=c++26 (test for errors, line 14) FAIL: g++.dg/cpp26/fold-constr3.C -std=c++26 (test for excess errors) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 13) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 19) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 20) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 21) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 23) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 28) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 29) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 30) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 32) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 37) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 38) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 39) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 41) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 47) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 51) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 56) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 60) FAIL: g++.dg/cpp26/fold-constr5.C -std=c++26 (test for errors, line 65) FAIL: g++.dg/cpp26/fold-constr6.C -std=c++26 (test for errors, line 20)
(In reply to Jakub Jelinek from comment #3) > BTW, with a modified version of fold-constr5.C which doesn't involve any > fold expanded constraints: I've filed PR116106 for that case as well as fold-constr5.C in the patch, which suffers from the same issue.
Created attachment 58793 [details] gcc15-pr115746-wip.patch Attaching latest version of the patch. I'm afraid I don't know enough about the parameter mapping/substitutions to finish this patch, so unassigning myself, hope somebody will find at least some parts of the patch useful.