https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117294

            Bug ID: 117294
           Summary: Concept swallow diagnostics when they're defined in
                    terms of type traits
           Product: gcc
           Version: 14.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: ---

Here's a simple, broken program:

#include <concepts>

template <std::default_initializable T>
auto make() {
    T t;
    return t;
}

struct A {
    explicit A(int) {}
};

template <typename T>
struct Foo {
    T a = 1;
};

auto tryit() {
    return make<Foo<A>>();
}


This (correctly) fails to compile, and the compile message does tell me A isn't
default constructible. Which... is okay (this is on
-fconcepts-diagnostics-depth=10, there's no more information than this):

<source>:19:24: error: no matching function for call to 'make<Foo<A> >()'
   19 |     return make<Foo<A>>();
      |            ~~~~~~~~~~~~^~
<source>:4:6: note: candidate: 'template<class T>  requires 
default_initializable<T> auto make()'
    4 | auto make() {
      |      ^~~~
<source>:4:6: note:   template argument deduction/substitution failed:
<source>:4:6: note: constraints not satisfied
In file included from <source>:1:
/modules/rhel8/gcc-14.1.0/include/c++/14.1.0/concepts: In substitution of
'template<class T>  requires  default_initializable<T> auto make() [with T =
Foo<A>]':
<source>:19:24:   required from here
   19 |     return make<Foo<A>>();
      |            ~~~~~~~~~~~~^~
/modules/rhel8/gcc-14.1.0/include/c++/14.1.0/concepts:159:13:   required for
the satisfaction of 'constructible_from<_Tp>' [with _Tp = Foo<A>]
/modules/rhel8/gcc-14.1.0/include/c++/14.1.0/concepts:164:13:   required for
the satisfaction of 'default_initializable<T>' [with T = Foo<A>]
/modules/rhel8/gcc-14.1.0/include/c++/14.1.0/concepts:160:30: note: the
expression 'is_constructible_v<_Tp, _Args ...> [with _Tp = Foo<A>; _Args = {}]'
evaluated to 'false'
  160 |       = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

On the other hand, if instead of using the concept std::default_initializeable,
I just wrote "class T"... the body of make<T> will fail to instantiate in a
different way. And the error that I get is overwhelmingly better:

<source>: In instantiation of 'constexpr Foo<A>::Foo()':
<source>:9:7:   required from 'auto make() [with T = Foo<A>]'
    9 |     T t;
      |       ^
<source>:23:24:   required from here
   23 |     return make<Foo<A>>();
      |            ~~~~~~~~~~~~^~
<source>:19:11: error: could not convert '1' from 'int' to 'A'
   19 |     T a = 1;
      |           ^
      |           |
      |           int

It would be really nice if concepts diagnostics were still able to tell me
__why__ something fails instead of just that it does.

Demo on compiler explorer: https://compiler-explorer.coredev.jt/z/cd6YYM

Reply via email to