https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111158
Bug ID: 111158 Summary: diagnostics, colors, and std::same_as Product: gcc Version: 13.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: barry.revzin at gmail dot com Target Milestone: --- Consider this broken example: #include <concepts> template <typename T> struct Optional { }; auto f() -> Optional<int&>; auto g() #ifdef CONCEPTS -> std::same_as<Optional<int>> auto #else -> Optional<int> #endif { return f(); } The code is wrong, g() is specifying it returns Optional<int> but actually returns Optional<int&> and there's no conversion. Without concepts (just using a normal trailing return type), we get: <source>: In function 'Optional<int> g()': <source>:15:13: error: could not convert 'f()' from 'Optional<int&>' to 'Optional<int>' 15 | return f(); | ~^~ | | | Optional<int&> Compiler returned: 1 Pasting it here like this actually undersells how good the error it is, because it's actually in color, and the "int&" and "int" parts are a different color from the Optinoal<...> part, so it really visually stands out. Very nice, gcc devs! With concepts (the -> std::same_as<Optional<int>> auto approach), we get: <source>: In function 'auto [requires std::same_as<<placeholder>, Optional<int> >] g()': <source>:15:13: error: deduced return type does not satisfy placeholder constraints 15 | return f(); | ~^~ <source>:15:13: note: constraints not satisfied In file included from <source>:1: /opt/compiler-explorer/gcc-trunk-20230824/include/c++/14.0.0/concepts:57:15: required for the satisfaction of '__same_as<_Tp, _Up>' [with _Tp = Optional<int&>; _Up = Optional<int>] /opt/compiler-explorer/gcc-trunk-20230824/include/c++/14.0.0/concepts:62:13: required for the satisfaction of 'same_as<auto [requires std::same_as<<placeholder>, Optional<int> >], Optional<int> >' [with auto [requires std::same_as<<placeholder>, Optional<int> >] = Optional<int&>] /opt/compiler-explorer/gcc-trunk-20230824/include/c++/14.0.0/concepts:57:32: note: the expression 'is_same_v<_Tp, _Up> [with _Tp = Optional<int&>; _Up = Optional<int>]' evaluated to 'false' 57 | concept __same_as = std::is_same_v<_Tp, _Up>; | ~~~~~^~~~~~~~~~~~~~~~~~~ This isn't colored as nicely, and in general the diagnostic is I think quite a bit worse - it contains a lot of information that simply isn't relevant to the user. Like the fact that std::same_as is specified in this weird way in terms of this other __same_as thing. That's an implementation detail that pretty much never matters. It'd be nice if gcc had dedicated diagnostics handling for std::same_as<T, U> and just wrote that T and U are different types and applied the same kind of color highlighting that it does for the non-concepts case - which helped me a lot to visually call out that the distinction was int vs int&. Link to compiler explorer, where you can see the colors with gcc 13.2: https://godbolt.org/z/YaKjzvM98