> I see what you're saying. Perhaps any nested SFINAE contexts,
> i.e. an atomic constraint or the body of a requires-expression,
> should be considered to not be in the immediate context of the
> enclosing expression, so that only the innermost enclosing
> SFINAE context is considered to be unsatisfied, or evaluates
> to false. I think this could be a viable core issue.
This makes sense. And for an example where it actually makes a difference, we just need:
template<typename T>
requires ! requires { T::value; }
int func() { return 0;}
int a = func<int>();
Here we want to make sure the semantics of "T::value" aren't checked when substituting into the atomic constraint with expression "! requires { T::value; }", so that the requires-expression rules can determine the value is false, and then the constraint is in fact satisfied.
I would say that a couple of notes may fix the problem:
1) in [temp.constr.atomic], avoid the content (requires-seq) of a requires-expression to be considered part of the immediate context for the atomic constraint
2) in [expr.prim.req.nested], avoid the content (constrained-expression) of the nested requirement to be considered part of the immediate context for the nested requirement (in terms of what [expr.prim.req.general]-p5 states)
I think the nested-requirement case is already covered by "Substitution of template arguments into a nested-requirement does not result in substitution into the constraint-expression other than as specified in [temp.constr.constr]." Maybe that could be rephrased in terms of "the immediate context" to be more consistent - or maybe that would instead be more confusing given the state of that phrase "the immediate context".
I'd consider adding to the note in [temp.deduct.general]/7, which currently explains how a function's noexcept-specifier is instantiated, instead of during the TAD substitutions in the "deduction substitution loci". A template's constraints are a similar thing closely associated with the template declaration, but as you're clarifying, the substitution happens in a different way. Although in this case checking constraints always happens immediately after the TAD substitution (paragraph 5), it would still make clear that paragraph 8 "If a [TAD] substitution results in an invalid type or expression..." does not apply.
-- Andrew Schepler