https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102419
Jason Merrill <jason at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu.org Summary|[11/12 |[11/12 |Regression][concepts] |Regression][concepts] |[regression] |return-type-requirement of |return-type-requirement of |"Y<typename T::type>" does |"Y<typename T::type>" does |not check that T::type |not check that T::type |actually exists |actually exists | --- Comment #6 from Jason Merrill <jason at gcc dot gnu.org> --- Concept satisfaction was very deliberately designed in committee discussion to work differently from void_t, based on the normalized form rather than the concept-id as written. So this example is well-formed: template <class Tz> concept is_void = same_as(Tz, void); template <class Ta, class Tb> concept void_or_same = is_void<Ta> || same_as<Ta, Tb>; template <class T> void f() requires void_or_same<T,T&>; int main() { f<void>(); } // OK It definitely is an inconsistency with non-concept template-ids, but that's the design. C++20 national body comment CA104 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2103r0.html#CA104) is about one situation where we do need to substitute directly into the arguments, but it is a single exception to the rule. In the discussion of CA104 I suggested that we might want to reconsider this design (on 2019-11-08, if you want to look up the reflector message), and make my example above ill-formed, but we ended up making an exception instead. The behavior change you are seeing is from properly implementing http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1452r2.html and not a bug.