On Tue, 5 Nov 2024, Jason Merrill wrote:
> On 10/17/24 1:10 PM, Patrick Palka wrote:
> > On Thu, 17 Oct 2024, Patrick Palka wrote:
> >
> > > On Tue, 15 Oct 2024, Patrick Palka wrote:
> > >
> > > > On Tue, 15 Oct 2024, Patrick Palka wrote:
> > > >
> > > > > According to [temp.param]/11, the constraint on an auto NTTP is an
> > > > > associated constraint and so should be checked as part of satisfaction
> > > > > of the overall associated constraints rather than checked individually
> > > > > during coerion/deduction.
> > > >
> > > > By the way, I wonder if such associated constraints should be relevant
> > > > for
> > > > subsumption now?
> > > >
> > > > template<class T> concept C = true;
> > > >
> > > > template<class T> concept D = C<T> && true;
> > > >
> > > > template<C auto V> void f(); // #1
> > > > template<D auto V> void f(); // #2
> > > >
> > > > int main() {
> > > > f<0>(); // still ambiguous?
> > > > }
> > > >
> > > > With this patch the above call is still ambiguous despite #2 now being
> > > > more constrained than #1 because "more constrained" is only considered
> > > > for
> > > > function templates with the same signatures as per
> > > > https://eel.is/c++draft/temp.func.order#6.2.2 and we deem their
> > > > signatures
> > > > to be different due to the different type-constraint.
> > >
> > > I think I convinced myself that this example should be accepted, and the
> > > way to go about that is to replace the constrained auto in the NTTP type
> > > with an ordinary auto once we set its TEMPLATE_PARM_CONSTRAINTS. That
> > > way both templates have the same signature modulo associated constraints.
> >
> > Here is v2 which implements this in finish_constrained_parameter. Now
> > we can assert that do_auto_deduction doesn't see a constrained auto
> > during adc_unify deduction!
> >
> > -- >8 --
> >
> > Subject: [PATCH v2 2/2] c++: constrained auto NTTP vs associated constraints
> >
> > According to [temp.param]/11, the constraint on an auto NTTP is an
> > associated constraint and so should be checked as part of satisfaction
> > of the overall associated constraints rather than checked individually
> > during coerion/deduction.
> >
> > In order to implement this we mainly need to make handling of
> > constrained auto NTTPs go through finish_constrained_parameter so that
> > TEMPLATE_PARM_CONSTRAINTS gets set on them, and teach
> > finish_shorthand_constraint how to build an associated constraint
> > corresponding to the written type-constraint.
> >
> > @@ -18637,24 +18609,43 @@ finish_constrained_parameter (cp_parser *parser,
> > cp_parameter_declarator *parmdecl,
> > bool *is_non_type)
> > {
> > - tree decl = parmdecl->decl_specifiers.type;
> > + tree constr = parmdecl->decl_specifiers.type;
> > tree id = get_unqualified_id (parmdecl->declarator);
> > tree def = parmdecl->default_argument;
> > - tree proto = DECL_INITIAL (decl);
> > /* Build the parameter. Return an error if the declarator was invalid.
> > */
> > tree parm;
> > - if (TREE_CODE (proto) == TYPE_DECL)
> > - parm = cp_parser_constrained_type_template_parm (parser, id, parmdecl);
> > + if (is_constrained_auto (constr))
> > + {
> > + /* Constrained non-type parameter. */
> > + *is_non_type = true;
>
> Why not replace constr with an unconstrained auto here...
>
> > + parm = grokdeclarator (parmdecl->declarator,
> > + &parmdecl->decl_specifiers,
> > + TPARM, /*initialized=*/0, /*attrlist=*/NULL);
> > + /* Replace the type of this constrained (auto) NTTP with an ordinary
> > + auto; its constraint gets saved in TEMPLATE_PARM_CONSTRAINTS to be
> > + associated with the template. */
> > + if (parm != error_mark_node)
> > + TREE_TYPE (parm) = (AUTO_IS_DECLTYPE (constr)
> > + ? make_decltype_auto ()
> > + : make_auto ());
>
> ...rather than here? Doing it here seems unlikely to work for e.g.
>
> template <class T> concept C = __is_same(T,int);
> template <C auto *P> struct A { };
> int i;
> A<&i> a;
>
> Hmm, I suspect finish_shorthand_constraint just taking decltype(P) will also
> break.
Good point, it does break. It's not clear how to express and ultimately
mangle the constraint on P as an associated constraint. I guess we
could do C<decltype(*P)> for C auto*, but then what about for C auto&
(where we must check C on the referred-to type)?
>
> Jason
>
>