public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/97572] New: [c++ 20] Constraining is broken
@ 2020-10-25 19:21 dimitri.gorokhovik at free dot fr
  2020-10-25 22:06 ` [Bug c++/97572] " redi at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: dimitri.gorokhovik at free dot fr @ 2020-10-25 19:21 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 97572
           Summary: [c++ 20] Constraining is broken
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dimitri.gorokhovik at free dot fr
  Target Milestone: ---

The code:

constexpr bool any (bool) { return true; };
template <typename T> concept Any = requires (T t) { requires any (t); };
constexpr static int f (Any auto) { return 42; };
constexpr auto q = f (false);


when compiled as:

g++ -std=c++20  -o bug-9.o -c  bug-9.cpp


produces:

bug-9.cpp: In substitution of ‘template<class auto:1>  requires  Any<auto:1>
constexpr int f(auto:1) [with auto:1 = bool]’:
bug-9.cpp:5:28:   required from here
bug-9.cpp:3:63: error: ‘t’ is not a constant expression
    3 | template <typename T> concept Any = requires (T t) { requires any (t);
};
      |                                                      ~~~~~~~~~^~~~~~~
bug-9.cpp:5:28: error: no matching function for call to ‘f(bool)’
    5 | constexpr auto q = f (false);
      |                            ^
bug-9.cpp:4:22: note: candidate: ‘template<class auto:1>  requires  Any<auto:1>
constexpr int f(auto:1)’
    4 | constexpr static int f (Any auto) { return 42; };
      |                      ^
bug-9.cpp:4:22: note:   substitution of deduced template arguments resulted in
errors seen above


GCC version:

g++ (GCC) 11.0.0 20201025 (experimental)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
@ 2020-10-25 22:06 ` redi at gcc dot gnu.org
  2020-10-26 10:45 ` dimitri.gorokhovik at free dot fr
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2020-10-25 22:06 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think GCC is correct to reject this. any(t) is not a valid constraint.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
  2020-10-25 22:06 ` [Bug c++/97572] " redi at gcc dot gnu.org
@ 2020-10-26 10:45 ` dimitri.gorokhovik at free dot fr
  2020-10-26 11:37 ` redi at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: dimitri.gorokhovik at free dot fr @ 2020-10-26 10:45 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Dimitri Gorokhovik <dimitri.gorokhovik at free dot fr> ---
Fair enough, passing a boolean by value into 'any()' is evaluation of local
parameter 't', and that is prohibited (7.5.7.4/2). 

Doesn't this merit a better diagnostics though?

A slightly modified code:

constexpr bool any (bool) { return true; };
template <typename T> concept Any = requires (T t) { requires any (t); };
static_assert (Any <bool>);

produces:

constexpr bool any(bool)
<stdin>:2:63: error: ‘t’ is not a constant expression
<stdin>: At global scope:
<stdin>:3:16: error: static assertion failed
<stdin>:3:16: note: constraints not satisfied
<stdin>:2:31:   required by the constraints of ‘template<class T> concept Any’
<stdin>:2:37:   in requirements with ‘T t’ [with T = bool]
<stdin>:2:63: error: ‘t’ is not a constant expression
<stdin>:2:67: note: nested requirement ‘any(t)’ is not satisfied, because
<stdin>:2:68: error: cannot convert ‘T’ to ‘bool’
<stdin>:1:21: note:   initializing argument 1 of ‘constexpr bool any(bool)’

which completely leads to believe that the culprit is in the line 2 whereas it
is in the line 1 (which doesn't even have a 't')?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
  2020-10-25 22:06 ` [Bug c++/97572] " redi at gcc dot gnu.org
  2020-10-26 10:45 ` dimitri.gorokhovik at free dot fr
@ 2020-10-26 11:37 ` redi at gcc dot gnu.org
  2020-10-26 12:22 ` dimitri.gorokhovik at free dot fr
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2020-10-26 11:37 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
But the problem *is* in line 2:

<stdin>:2:63: error: ‘t’ is not a constant expression

To evaluate any(t) in a constant expression you need t to be a constant
expression, and it isn't.

I suppose the diagnostic could be improved to clarify that local parameters of
a requires-expression are never constant expressions.


Clang gives a different error, but I don't think the reason it gives for the
error is actually helpful:

any.C:3:1: error: static_assert failed
static_assert (Any <bool>);
^              ~~~~~~~~~~
any.C:3:16: note: because 'bool' does not satisfy 'Any'
static_assert (Any <bool>);
               ^
any.C:2:68: note: because 'any(t)' would be invalid: constraint variable 't'
cannot be used in an evaluated context
template <typename T> concept Any = requires (T t) { requires any (t); };
                                                                   ^
1 error generated.


"cannot be used in an evaluated context" seems odd given that all expressions
in a requirements-body are unevaluated operands.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
                   ` (2 preceding siblings ...)
  2020-10-26 11:37 ` redi at gcc dot gnu.org
@ 2020-10-26 12:22 ` dimitri.gorokhovik at free dot fr
  2021-04-27 10:22 ` redi at gcc dot gnu.org
  2021-04-27 10:27 ` redi at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: dimitri.gorokhovik at free dot fr @ 2020-10-26 12:22 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Dimitri Gorokhovik <dimitri.gorokhovik at free dot fr> ---
I probably cannot objectively tell anymore which one is better, since I just
read the specification. 

However, subjectively, Clang's diagnostics:

a) seems to have phrasing much closer to the spec, and

b) contains less misleading information:

-- the champion here is GCC's "error: cannot convert ‘T’ to ‘bool’" -- whereas
'T' *is*, in fact, 'bool'. (Note that this msg also has a status of a full
error in its own right, not just a note.)

-- arguably, a close contender is "error: ‘t’ is not a constant expression".
Understanding how it can happen was hard to me. 't' looks as constant as they
get with requires-local-parameters (I mean, constexpr-ness of a local-parameter
here should be understood as coming only from its declaration shouldn't it?).
The (S s) form of requires-local-var is a common form, so when the compiler
says 's' is not a constant expression' here, how would it be constant in other
situations?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
                   ` (3 preceding siblings ...)
  2020-10-26 12:22 ` dimitri.gorokhovik at free dot fr
@ 2021-04-27 10:22 ` redi at gcc dot gnu.org
  2021-04-27 10:27 ` redi at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2021-04-27 10:22 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The diagnostic is different now and the "cannot convert 'T' to 'bool'" part is
gone. For comment 0 we get:


97572.C: In substitution of 'template<class auto:1>  requires  Any<auto:1>
constexpr int f(auto:1) [with auto:1 = bool]':
97572.C:4:22:   required from here
97572.C:2:63: error: 't' is not a constant expression
    2 | template <typename T> concept Any = requires (T t) { requires any (t);
};
      |                                                      ~~~~~~~~~^~~~~~~
97572.C:4:22: error: no matching function for call to 'f(bool)'
    4 | constexpr auto q = f (false);
      |                    ~~^~~~~~~
97572.C:3:22: note: candidate: 'template<class auto:1>  requires  Any<auto:1>
constexpr int f(auto:1)'
    3 | constexpr static int f (Any auto) { return 42; };
      |                      ^
97572.C:3:22: note:   substitution of deduced template arguments resulted in
errors seen above


This seems good enough to me. It tells you that 't' is not a constant
expression, which is correct, and that means that the call any(t) is not a
constant expression and so can't be used as the operand to 'requires'. Because
that constraint fails, it means that you can't call f(Any auto), and so there
is not matching function.

I still think it might be helpful to say that local parameters of a
requires-expression are never constant expressions.

For comment 2 we get:

97572-c2.C:2:63: error: 't' is not a constant expression
    2 | template <typename T> concept Any = requires (T t) { requires any (t);
};
      |                                                      ~~~~~~~~~^~~~~~~
97572-c2.C:3:16: error: static assertion failed
    3 | static_assert (Any <bool>);
      |                ^~~~~~~~~~
97572-c2.C:3:16: note: constraints not satisfied
97572-c2.C:2:31:   required by the constraints of 'template<class T> concept
Any'
97572-c2.C:2:37:   in requirements with 'T t' [with T = bool]
97572-c2.C:2:63: error: 't' is not a constant expression
    2 | template <typename T> concept Any = requires (T t) { requires any (t);
};
      |                                                      ~~~~~~~~~^~~~~~~
97572-c2.C:2:63: error: 't' is not a constant expression

Again, this seems good enough.

(In reply to Dimitri Gorokhovik from comment #4)
> -- arguably, a close contender is "error: ‘t’ is not a constant expression".

But it's absolutely correct.

> Understanding how it can happen was hard to me. 't' looks as constant as
> they get with requires-local-parameters (I mean, constexpr-ness of a
> local-parameter here should be understood as coming only from its
> declaration shouldn't it?).

Yes, and function parameters are *never* constant expressions, even in
consteval functions. Why do you think it would be different here?

constexpr int f(int n) { static_assert(n!=1); }

ce.C:1:41: error: ‘n’ is not a constant expression

It's constexpr-ness *does* come from its declaration, and it's not declared as
a constant.

> The (S s) form of requires-local-var is a common
> form, so when the compiler says 's' is not a constant expression' here, how
> would it be constant in other situations?

By using ... a constant of course.

e.g. a literal like 1 or true, or a constant like std::is_integral_v<T>.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug c++/97572] [c++ 20] Constraining is broken
  2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
                   ` (4 preceding siblings ...)
  2021-04-27 10:22 ` redi at gcc dot gnu.org
@ 2021-04-27 10:27 ` redi at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: redi at gcc dot gnu.org @ 2021-04-27 10:27 UTC (permalink / raw)
  To: gcc-bugs

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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |WORKSFORME

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I'm closing this as WORKSFORME, since "constraining is broken" is false, and
the diagnostic is correct.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2021-04-27 10:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-25 19:21 [Bug c++/97572] New: [c++ 20] Constraining is broken dimitri.gorokhovik at free dot fr
2020-10-25 22:06 ` [Bug c++/97572] " redi at gcc dot gnu.org
2020-10-26 10:45 ` dimitri.gorokhovik at free dot fr
2020-10-26 11:37 ` redi at gcc dot gnu.org
2020-10-26 12:22 ` dimitri.gorokhovik at free dot fr
2021-04-27 10:22 ` redi at gcc dot gnu.org
2021-04-27 10:27 ` redi at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).