[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-14 Thread ing.russomauro at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #10 from mauro russo  ---
As comment about point (a), I hope to be right in referring the following
standard text from [temp.constr.normal]-p(1.4):

"The normal form of a concept-id C is the normal form of
the constraint-expression of C, after substituting A1 , A2 , ..., An for C’s
respective template parameters in the parameter mappings in each atomic
constraint. ..."

This seems to confirm the statement that unsued parameter do not partecipate in
the generation of the normal form of the constraints associated to a template,
because [temp.constr.decl]-p3, in turn, reads:
"... the associated constraints are the normal form of ..."


Another contribute to (b), beyond the aforementioned [expr.prim.req.general] -
p5, there is also [temp.constr.atomic]-p3, reading:

"To determine if an atomic constraint is satisfied, the parameter mapping and
template arguments are first substituted into its expression. If substitution
results in an invalid type or expression in the immediate context of the atomic
constraint, the constraint is not satisfied. ... "

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-13 Thread ing.russomauro at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #9 from mauro russo  ---
ok, I would say that, for point (b),

§13.5.2.2 [temp.constr.op] - p2 and p3:

"2 A conjunction is a constraint taking two operands. To determine if a
conjunction is satisfied, the satisfaction of the first operand is checked. If
that is not satisfied, the conjunction is not satisfied. Otherwise, the
conjunction is satisfied if and only if the second operand is satisfied."

"3 A disjunction is a constraint taking two operands. To determine if a
disjunction is satisfied, the satisfaction of the first operand is checked. If
that is satisfied, the disjunction is satisfied. Otherwise, the disjunction is
satisfied if and only if the second operand is satisfied."


confirms your statement, together the note after Example 1 in part 4:

"... the constraint sizeof(char) > 1 is not satisfied; the second operand is
not checked for satisfaction."

I will discuss somewhere else whether it may be better to add a note that
ill-forming does not care if an operand constraint is not checked at all.


Please, may you tell me what about my residual doubt on point (a) ?

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-12 Thread ing.russomauro at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #8 from mauro russo  ---
I see, it makes sense.

However, I hope not to be too tedious to ask explicit references for the rules
you stated:

a) ignore requirements on parameters not used in the evaluation of a concept.

b) ignore errors in non-immediate context during a clause if previous clauses
already determined (in terms of boolean combination among constraints) the
acceptance or rejection.


I am unable to find both of them.


In the current standard draft, I could find other topics we discussed:

§7.5.8.1 [expr.prim.req.general] - p5:

1) "... can result in the formation of invalid types or expressions in the
immediate context of its requirements ... In such cases, the
requires-expression evaluates to false; it does not cause the program to be
ill-formed."

Indeed, this confirms your statement that, for the erros in a lambda, the
'savage' does not apply and the program is ill-formed.


2) "... The substitution and semantic constraint checking proceeds in lexical
order and stops when a condition that determines the result of the
requires-expression is encountered."

This part is a kind of what I was looking for, about point b) above, but it
applies only to multiple requirements inside a single requires expression, that
is, not to multiple combined constraints.

About multiple combined constraints, I cannot find evidences of (b) from
sections as §13.5.3 [temp.constr.decl], §13.5.4 [temp.constr.normal], §13.5.5
[temp.constr.order]

Similary, I cannot find evidences of (a) from sections as §13.3 [temp.names],
where p9 reads:

"A concept-id is a simple-template-id where the template-name is a
concept-name. A concept-id is a prvalue of type bool, and does not name a
template specialization. A concept-id evaluates to true if the concept’s
normalized constraint-expression (13.5.3) is satisfied (13.5.2) by the
specified template arguments and false otherwise."

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #7 from Andrew Pinski  ---
(In reply to mauro russo from comment #6)
> ok, I will also check for the confirmation from standard text.
> 
> What about the fact that for func2, second clause is ignored after that
> first one fails ?

Yes && is short cutting for concepts. The second clause does not matter if the
first one fails with &&. If it was || and the first clause passes, then the
second part does not matter. It is the same as if you did f()&&g() g() is not
executed if f() returns false right?

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread ing.russomauro at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #6 from mauro russo  ---
ok, I will also check for the confirmation from standard text.

What about the fact that for func2, second clause is ignored after that first
one fails ?
Do you confirm it is fair ?
Do you confirm that this is 'stronger' than the fact that second clause uses
again a lambda which is not an immediate context ? (i.e., a kind of if
constexpr that  does not need for the excluded block to be compilable).

I will also open a bug report for MVSC about func1 and func1b.
So, based on your comments, on func1b, both MVSC and Clang behave incorrectly
but for different motivations.

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #5 from Andrew Pinski  ---
(In reply to Andrew Pinski from comment #3)
> lambda are not considered an immediate context which is why func1 fails for
> GCC and clang.
See PR 103760 for that.

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

Andrew Pinski  changed:

   What|Removed |Added

 Resolution|--- |INVALID
 Status|UNCONFIRMED |RESOLVED

--- Comment #4 from Andrew Pinski  ---
(In reply to Andrew Pinski from comment #3)
> lambda are not considered an immediate context which is why func1 fails for
> GCC and clang.
> 
> Also unused template arguments for concepts are not taken into account so in
> this cases the lambdas for C2 are ignored. This is why GCC works (clang has
> a bug in this area; let me find that issue).

See PR 105615 and PR 102419.


So GCC is correct here.

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #3 from Andrew Pinski  ---
lambda are not considered an immediate context which is why func1 fails for GCC
and clang.

Also unused template arguments for concepts are not taken into account so in
this cases the lambdas for C2 are ignored. This is why GCC works (clang has a
bug in this area; let me find that issue).

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #2 from Andrew Pinski  ---
(In reply to mauro russo from comment #1)
> sorry, let me re-style the main() function with related comments, to adapt
> this 80-columns views.

Note you can attach a file which a field which you can paste/type into instead
of needing to attach a file from your computer. This is very useful for this
kind of issues too.

[Bug c++/118398] Resolving lambda expression decltype prioritized over the option to consider failed required concept using that type as argument

2025-01-10 Thread ing.russomauro at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118398

--- Comment #1 from mauro russo  ---
sorry, let me re-style the main() function with related comments, to adapt this
80-columns views.



int main(){
func1(std::set{}); // - gcc behaves as clang about the need to resolve
//   lambda types before deciding for the
constraint 
//   satisfaction.
// - MVSC rejects second overload and selects the
//   first one, that is, it considers constrain
//   failed due to unfair "it->first" code
//   in the lambda expression.
func1(std::map{}); // all compilers correctly select second
// overload.
// This time, no reverse problem about "*it",
// and then concept C fails for set iterators.

func1b(std::set{}); // - gcc wrongly considers both overloads as
 //   eligible, ignoring that "it->first" does not
 //   work for second overload, likely as
 //   side-effect of the fact that Cb concept
 //   resolves as true.
 // - clang consistently behaves as for func1.
 // - MVSC rejects instead second overload, exactly
as for func1.
//func1b(std::map{}); // all compilers correctly consider
ambiguous 
   // overloads.

func2(std::set{}); // all compilers selects first overload (i.e., gcc
// and clang behaves differently about lambda type
// resolution)
func2(std::map{}); // all compilers select second overload,
// as for func1.
}