https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118698
--- Comment #17 from Patrick Palka <ppalka at gcc dot gnu.org> ---
(In reply to Jason Merrill from comment #15)
> (In reply to Patrick Palka from comment #12)
> > Substituting <T,foo> into <decltype([]{},T> seems like a partial
> > substitution to me. If the lambda itself had any template parameters of its
> > own, or autos, we wouldn't want to reduce their level, so it seems
> > tf_partial should be set during normalization?
>
> Hmm, perhaps, it certainly seems related to the use of tf_partial in
> instantiate_template. But doing that brings back the tsubst_lambda_expr
> EXTRA_ARGS problems.
Yeah, passing tf_partial wouldn't be sufficient IIUC.
>
> I think part of the problem is that tf_partial has gotten overloaded. The
> original meaning was "we only have arguments for some of the parms at this
> level". The use in instantiate_template has broadened the meaning to
> "substituting without changing the number of levels of parms". Which would
> also apply in normalization.
>
> But it's unclear to me why we would want EXTRA_ARGS in that broader sense;
> if we have all the args, we're just substituting them, I'd expect that to
> work fine with the "leave auto alone" meaning.
Even with level-less auto, what about a generic lambda's own template
parameters? We still need to avoid lowering their levels prematurely during a
dependent/partial substitution.
template<class T>
struct A {
template<class U>
using type = decltype([]<class V>{});
void f() { type<int> t; }
};
template void A<char>::f();
Here we eagerly substitute the alias template ahead of time with a full set of
generic arguments {{T},{int}}. And then at instantiation time we substitute
again with a full set of concrete arguments {{char},{int}}. If we don't pass
tf_partial the first time around, the level of V would be prematurely lowered
to 1 which causes the instantiation time substitution to misbehave.
>
> And the assumption in add_extra_args seems wrong for the original sense; in
> general with tf_partial we would not have a full set of template arguments,
> though we might have enough of them to do the substitution. And we should
> have the right number of levels, which is the point of that change.
At least for the fn_type_unification and coerce_template_parms call sites that
pass tf_partial under the old meaning, we should always have a full set of
template arguments (with some arguments missing in the innermost level). Ditto
the instantiate_template call site under the broader meaning.