On Wed, Feb 12, 2025 at 12:03 AM mauro russo via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
I will try to shorten the post,

referring for the moment to the first topic only (A) from previous post (2800):

do you believe that when an atomic constraint is made by a requires-expression,
the content of the requires-expression body (i.e., requirement-seq) is not part of the immediate context of the atomic constraint ?

I do, as it currently seems more consistent to me, based on the different perspective provided by the text of the parts [expr.prim.req.general]-p5, [temp.constr.atomic]-p3, and [temp.res.general]-p(6.4).


Do you believe that the fact that it is not part of the immediate context of the atomic constraint is already well clear in the standard ?
I am not sure. I currently suppose that a note similar to [temp.deduct.general]-p9 would be needed,
unless I have missed where we may get the basic definition of immediate context: I only see double quotes used for it in [temp.deduct.general]-p8 (Note 6) (excluding library part)


Hope to get some answer on this reduced post by any moderator.

Il giorno mer 29 gen 2025 alle ore 23:57 mauro russo <ing.russomauro@gmail.com> ha scritto:
hello,

I am writing again about the topic of:
https://lists.isocpp.org/std-discussion/2025/01/2783.php
and
https://lists.isocpp.org/std-discussion/2025/01/2787.php

for which I have got no answer.

I may suppose you are intentionally lowering the frequence to answer me because of I am posting a quite number of questions in these months. That's ok to me, but I hope you may increase the frequency in case no other discussions are in place by other users.

If you want faster replies, you need to get better at being concise:
  • lead with an example
  • if all compilers agree on the behavior of the example, ask something like "why does this compile?" or "why doesn't this compile?" or "why does this print 1 and not 2?", etc
  • if compilers disagree on the behavior of the example, say so and provide a godbolt link
  • keep the explanation short: people rarely have time to read walls of text
  • don't scatter the actual questions throughout the email
I suggest looking at descriptions of some recent core issues to get a sense of how to communicate these kinds of questions concisely.
 

I will try again to recap the 3 questions. related to the constraints.

As general idea, I have got that an invalid type/expression leads the constraint just to fail if it is in immediate-context, otherwise to an ill-formed program if in non-immediate-context (e.g., in the body of a lambda expression),
provided that the verification of that type/expression is triggered by the fact that previous parts of the constraint (in the lexical order, e.g., in the pieces of a requires expression, or in the combined list of atomic constraints for a normal form) weren't able to determine already an overall result for the constraint (e.g., false for an AND combination, or true for an OR combination),
but also that an invalid type/expression always in place for a templated entity (i.e., regardless of the instantiation) represents an IFNDR case.

That said, I have reported in https://lists.isocpp.org/std-discussion/2025/01/2783.php the text associated to both requires expression ([expr.prim.req.general]-p5) and atomic constraint ([temp.constr.atomic]-p3  and  [temp.res.general]-p(6.4)),
and I have noticed two potential problematic topics when an atomic constraint is made by a requires expression.
I recall them in the following, and refine/fix details of the discussion.

Before discussing the detail of the first 2 questions, it is important to highlight that the normal form of the constraints associated to a function, is built according to rules from [temp.constr.normal], where no 'explosion' is indicated in case of requires expression, which means that a requires expression boils down to be an atomic constraint even when it contains multiple requirements (simple, type, compound, nested: [expr.prim.req.general]-p1).

A) the first topic is for the case when that requires expression contains a nested requirement, which therefore contains a constraint-expression, in turn supposed to contain AND / OR operators, combining further nested constraints/requirements; let's now suppose that one of these nested ones contains an invalid type/expression, but also that another constraint/requirement preceding in the lexical order, allows to provide a true value for the original requires expression.
If I would exactly apply the text of [temp.constr.atomic]-p3, then it reads that an invalid type/expression (in immediate context) leads soon the constraint to be not satisfied, whereas the rules from [expr.prim.req.general]-p5 postpone the check of invalid type/expression for each contained requirement only after that previous requirements have already been checked and successfully verified (true result), and similarly the rules from [temp.constr.op]-p2/p3 state that the constraints conjunctions and disjunctions are checked one by one, ignoring the residual ones as soon as a constraint allows to get a logical overall result.
Please, note that in my original post (2783), I erroneuosly considered a case with false overall logical result for the requires expression, and invoked only the rules from [expr.prim.req.general]-p5, but this is not a conflict because the final result as false is provided by both [temp.constr.atomic]-p3 and [expr.prim.req.general]-p5.

As highlighted in the second post (2787), I really believe that everything becomes clear and well consistent if the presence of an invaild type/expression within a requires expression does not mean that the requires expression is itself an invalid expression. Indeed, this would represent a hierarchical separation between the atomic constraint and what is inside the requires expression.
Please, let me know if this is true, and if in your opinion this is in some way already clear in the standard for any motivation (e.g., concept of 'immediate context', or anything else).
If the solution is in the definition of 'immediate context', don't you believe that the standard might state clearly something (similar to [temp.deduct.general]-p9) about the requirement-body not being part of the immediate context of an atomic constraint corresponding to the requires expression ? However, in such case, I would be also afraid of formally incorrectness about the effect of invalid within the requirements of the requires-expression (i.e., invalid in a non-immediate context for the original atomic constraint), and therefore some more note should be added to clarify that any decision is based on the rules for those requirements.
Otherwise (if none of the previous ones apply), do you believe (as I do) that the standard may be clarified in [temp.constr.atomic]-p3 when an atomic constraint is made by a requires expression, and eventually even in [expr.prim.req.general]-p5 in order to introduce a similar 'hierarchical separation' when one of the requirements is a nested requirement ? (but I don't know if it was really intended to have also the second mentioned kind of hierarchy... likely not).


B) the second topic is related to the cases of IFNDR when the invalid type/expression is always in place; indeed, [expr.prim.req.general]-p5 reads that the IFNDR is there anyway, which means regardless of any satisfation check is performed or not involving the part containing the invalid type/expression; on the contrary, [temp.res.general]-p(6.4) reads that the IFNDR is only effective with the additional condition that no satisfaction check is performed on the constraint-expression containing the always-invalid type/expression.
But, what happens if the invalid is in an immediate context, a check is performed, therefore (based on [temp.constr.atomic]-p3) the constraint is just not satisfied but no ill-forming is notified by the compiler ?
Is it really wanted to drop the IFNDR just because a check was performed ?
Can I state that if the invalid is inside a requires expression, the IFNDR remains anyway in place based on 
[expr.prim.req.general]-p5 ?
Was also here any hierarchical separation intended as discussed for previous topic ?
Note also that 
[temp.res.general]-p(6.4) makes no distinction between immediate and non-immediate contexts, nor between templated and non-templated entities -> is it really wanted not to have IF for non-immediate contexts ? Not even for non-templated entities (for them, Note 1 in [expr.prim.req.general]-p5 for requires expressions states IF instead of IFNDR) ?
Note finally that last part of 
[expr.prim.req.general]-p5 (after Note 1) seems not to be specific for immediate or non-immediate contexts, but I do believe that for non-immediate ones the intended behaviour is IF instead of IFNDR, isn't it ?


Last topic, with a short question:
C) (which was presented since the post 2783):
In [temp.constr.normal], the example in p1.4) reads that the atomic constraint-expression 'true' has empty mapping.
The point is that no rule 
from [temp.constr.normal] exactly states the possibility to get an empty mapping.
We have part p(1.9) as default case always indicating an identity mapping. I guess it should be extended to indicate empty mapping when the expression is constant, that is, not involving any template parameter (you know
for sure the best formal words to say it there).
I don't believe it's fair to consider the definition of this special case just through the example in p(1.4).


Thank you.


Il giorno gio 16 gen 2025 alle ore 01:15 mauro russo <ing.russomauro@gmail.com> ha scritto:
I thought about the topics once more.
(https://lists.isocpp.org/std-discussion/current/2783.php)

Maybe the solution about the potential ambiguity between the rules on atomic constraints and the rules on requires-clause, is that a requires-clause including invalid type/expression, is not itself an invalid expression, as this would mean that an atomic constraint being a requires-clause means that the requires-clause is well-formed (valid expression) and so only the rules for requires-clause apply.

Please, confirm this is true. However, in such a case, I would suggest to add a short note in [temp.constr.atomic]. I am not convinced such a note would be a 'tutoring'... but you can choose.

Additionally, I still wonder about the text in [temp.res.general] - p(6.4), which appear with a different spirit from [expr.prim.req.general] - p5, because in case the always-ill-forming is in an immediate context and there is any code triggering the check involving that context, the former does not lead to IFNDR (nor to a compilation error triggered by the existing check), whereas the latter does it (IFNDR for immediate context, and of course compilation error for non-immediate context).

Even my third doubt, that is about the need to specify the generation of atomic constraints with empty mapping, still applies.

Please, read previous message (mentioned above) of this thread for the complete background.
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion


--
Brian Bi