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
  • [Bug c++/111158] New: diagnosti... barry.revzin at gmail dot com via Gcc-bugs

Reply via email to