https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97407
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Reduced:
template<typename T> T&& declval;
template<typename R> decltype(declval<R&>().begin()) begin_impl(R&);
template<typename R>
using iter_type_impl = decltype(begin_impl(declval<R&>()));
template<typename Wat>
struct unrelated
{
using erm = iter_type_impl<Wat>;
};
template<typename R>
using iterator_t = iter_type_impl<R>;
template<typename T> concept False = false;
template<typename R>
requires False<iterator_t<R>>
void f(R&)
{ }
int main()
{
int a[2];
f(a);
}
alias.C: In function ‘int main()’:
alias.C:27:6: error: use of function ‘void f(R&) [with R = int [2]]’ with
unsatisfied constraints
27 | f(a);
| ^
alias.C:21:6: note: declared here
21 | void f(R&)
| ^
alias.C:21:6: note: constraints not satisfied
alias.C: In instantiation of ‘void f(R&) [with R = int [2]]’:
alias.C:27:6: required from here
alias.C:17:30: required for the satisfaction of ‘False<decltype
(begin_impl(declval<Wat&>()))>’ [with Wat = int[2]]
alias.C:17:38: note: the expression ‘false’ evaluated to ‘false’
17 | template<typename T> concept False = false;
| ^~~~~
Here we print decltype (begin_impl(declval<Wat&>())) which would be better left
as iterator_t<R>, especially because "Wat" comes from a completely unrelated
class template which isn't even instantiated, but happens to use the same alias
template as iterator_t uses.