[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

Erich Keane via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 17 06:02:25 PDT 2023


erichkeane added a comment.

In D146178#4200821 <https://reviews.llvm.org/D146178#4200821>, @rsmith wrote:

> The approach of attempting to adjust the depth here is not correct, and we should rip this whole mechanism out and reimplement it.  Consider this closely related testcase:
>
>   template<typename T, typename U>
>   concept Concept = true;
>   
>   template<typename T>
>   struct A
>   {
>     template<Concept<T> V>
>     void C(V&& t);
>   };
>   
>   template<>
>   template<Concept<int> V>
>   void A<int>::C(V&& t)
>   {}
>
> Clang rejects this because it's trying to compare `Concept<T>` from the declaration against `Concept<int>` from the explicit specialization.
>
> The right way to fix that and the issue being addressed here is that, rather than adjusting the depths, we should substitute the outer template arguments from the scope specifier (`A<int>::`) into the constraint before performing the comparison. (In the special case where none of the outer template parameters are used by the inner template, that does effectively just adjust the depths of any inner template parameters.)
>
> The relevant language rule was introduced by the resolution of CA104 in P2103R0 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2103r0.html#ca104> (which Clang's status page incorrectly marks as complete in Clang 10). In particular, see temp.constr.decl/4 <https://eel.is/c++draft/temp.constr.decl#4> for the rule that we should implement, but don't:
>
>> When determining whether a given introduced constraint-expression `C1` of a declaration in an instantiated specialization of a templated class is equivalent ([temp.over.link]) to the corresponding constraint-expression `C2` of a declaration outside the class body, `C1` is instantiated. If the instantiation results in an invalid expression, the constraint-expressions are not equivalent.
>
> So, in this case, we're supposed to instantiate the constraint expression `Concept<T>`, substituting the template arguments of `A` into it (in a SFINAE context).

IIRC, the original motivation for this attempt was that we frequently compare template arguments, even in cases where that isn't permitted?  I had sent you a couple of emails when I was attempting this, but you'd not gotten a chance to respond.  I think I came up on this as the only way to do this without instantiating the constraint (which I recall you'd said was not the right way to compare constraints at one point?).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146178/new/

https://reviews.llvm.org/D146178



More information about the llvm-commits mailing list