================
@@ -1876,11 +1901,25 @@ namespace {
                               TemplateParameterList *OrigTPL)  {
       if (!OrigTPL || !OrigTPL->size()) return OrigTPL;
 
+      std::optional<MultiLevelTemplateArgumentList> OldMLTAL;
+      // We need to preserve the lambda depth in parameter mapping.
+      // Otherwise the template argument deduction would fail, if we reduced 
the
+      // depth too early.
+      if (SemaRef.inParameterMappingSubstitution() &&
+          getDepthAndIndex(OrigTPL->getParam(0)).first >=
+              TemplateArgs.getNumSubstitutedLevels())
+        OldMLTAL = ForgetSubstitution();
----------------
zyn0217 wrote:

> Also, I don't see how the level check is necessary. 

@mizvekov

The fact is that we will transform the lambda expression in both building and 
substitution of parameter mapping.

Say we have

```cpp
template<auto Pred, typename... Ts>
concept PredicateFor_bad = pass_a_concept_inside_a_lambda<[]<typename... Xs>
                                          
requires(__is_same(decltype(Pred.template operator()<Xs>()), bool) and ...)
                                      {},
                                      Ts...>;
```

When building, we only have outer template arguments `<Pred, <Ts...>>`, and 
since the transform of parameter list will reduce the depth of <Xs...> anyway 
if only partial template arguments are provided, depth of <Xs> will be 
converted to 0.

And in the second transform where we started to substitute real template 
arguments into parameter mapping (i.e. when we have `<Pred=lambda, Ts=<int, 
int, int>>`), the depth of `Xs` is reduced before deduction happens. This 
results in a -1 depth during argument deduction and thus we won't have a 
correct template argument list when checking the inner constraint.

Note that we didn't transform the lambda expression in the second transfrom, 
because the lambda was seen as non-dependent. I do want the lambda to have a 
second transform, because otherwise we don't have a way to get substituted 
`Pred` in constraint evaluation. (`Pred` is normalized and we have to evaluate 
the lambda's inner constraint during parameter mapping substitution, when we 
dont have any proper template arguments at that moment, which is an 
egg-and-chicken problem though)

https://github.com/llvm/llvm-project/pull/195995
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to