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.