Skip to content

Class template partial specialization with concept-auto non-type parameter is not supported #77377

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Fedr opened this issue Jan 8, 2024 · 5 comments
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts confirmed Verified by a second party

Comments

@Fedr
Copy link

Fedr commented Jan 8, 2024

In this program

#include <concepts>

template <auto>
struct A;

template <std::same_as<int> auto p>
struct A<p> {};

A<0> a;

A<auto> is a class template with non-type parameter, and A<std::same_as<int> auto> is its specialization for int parameters. The program is accepted by GCC and MSVC, but Clang complains:

error: class template partial specialization is not more specialized than the primary template [-Winvalid-partial-specialization]

Online demo: https://godbolt.org/z/ee4TcPY5K

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed new issue labels Jan 8, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 8, 2024

@llvm/issue-subscribers-clang-frontend

Author: None (Fedr)

In this program ``` #include <concepts>

template <auto>
struct A;

template <std::same_as<int> auto p>
struct A<p> {};

A<0> a;

`A&lt;auto&gt;` is a class template with non-type parameter, and `A&lt;std::same_as&lt;int&gt; auto&gt;` is its specialization for `int` parameters. The program is accepted by GCC and MSVC, but Clang complains:

error: class template partial specialization is not more specialized than the primary template [-Winvalid-partial-specialization]

Online demo: https://godbolt.org/z/ee4TcPY5K
</details>

@cor3ntin cor3ntin added concepts C++20 concepts confirmed Verified by a second party labels Jan 10, 2024
@cor3ntin
Copy link
Contributor

Interestingly, it does work with a requires clause
https://godbolt.org/z/bYM43r4Yr

@erichkeane

@zyn0217
Copy link
Contributor

zyn0217 commented Jan 11, 2024

We have to compare the template parameter equivalence before going through the constraint check, per [temp.func.order]p6.2.2:

Otherwise, if the corresponding template-parameters of the template-parameter-lists are not equivalent [temp.over.link]... neither template is more specialized than the other.

And the definition for 'equivalent' is at [temp.over.link]p6.3:

Two template-parameters are equivalent under the following conditions:

if they declare non-type template parameters, they have equivalent types ignoring the use of type-constraints for placeholder types

And this is implemented by bc62fb9.

Interestingly, it does work with a requires clause
https://godbolt.org/z/bYM43r4Yr

I think this could also explain why using a requires expression does work -- the parameters are considered equivalent that way.

(I'm not 100% sure the standard is intended to reject such cases. CC @zygoloid for some opinions.)

@zygoloid
Copy link
Collaborator

And the definition for 'equivalent' is at [temp.over.link]p6.3:

Two template-parameters are equivalent under the following conditions:
if they declare non-type template parameters, they have equivalent types ignoring the use of type-constraints for placeholder types

And this is implemented by bc62fb9.

In this case, the template parameters are equivalent, so we should continue to [temp.func.order]/6.4 which orders the function templates based on their constraints.

zyn0217 added a commit to zyn0217/llvm-project that referenced this issue Jan 19, 2024
vsaulue added a commit to vsaulue/Gustave that referenced this issue Apr 24, 2024
sdkrystian added a commit that referenced this issue May 16, 2024
…92425)

When the argument passed to `ASTContext::getUnconstrainedType` is an
unconstrained `AutoType`, will return the argument unchanged. However,
when called with a constrained `AutoType`, an unconstrained,
non-dependent `AutoType` will be returned even if the argument was
dependent. Consider the following:
```
template<typename T>
concept C = sizeof(T) == sizeof(int);

template<auto N>
struct A;

template<C auto N>
struct A<N>; // error: class template partial specialization is not more specialized than the primary template
```
When comparing the template parameters for equivalence,
`ASTContext::getUnconstrainedType` is used to remove the constraints per
[temp.over.link] p6 sentence 2. For the template
parameter `N` of the class template, it returns a dependent `AutoType`.
For the template parameter `N` of the class template partial
specialization, it returns a non-dependent `AutoType`. We subsequently
compare the adjusted types and find they are not equivalent, thus we
consider the partial specialization to not be more specialized than the
primary template per [temp.func.order] p6.2.2.

This patch changes `ASTContext::getUnconstrainedType` such that the
dependence of a constrained `AutoType` will propagate to the returned
unconstrained `AutoType`. This causes the above example to be correctly
accepted, fixing #77377.
@sdkrystian
Copy link
Member

Closed by #92425

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" concepts C++20 concepts confirmed Verified by a second party
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

7 participants