<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/104592>104592</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[clang] The timing of checking whether a constraint is self-dependent is unclear
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang:frontend,
concepts
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
zyn0217
</td>
</tr>
</table>
<pre>
This was uncovered while I was working on the implementation of CWG2369 in https://github.com/llvm/llvm-project/issues/54440; I ran into a libcxx test regression, and that test failure turned out to be a discrepancy in the implementation.
The pre-existing issue is as follows (thanks to @cor3ntin who helped to find out the nuance across GCC and Clang):
```cpp
template <class Tp>
concept C = requires(Tp t) { f(t); };
struct S {};
// template <typename T = void>
auto f(S) { return 1; } // #1
template <class T>
requires C<T>
auto f(T); // #2
S p;
int i = f(p);
```
(https://gcc.godbolt.org/z/vM61xxbKz)
Despite whether # 1 is a template, Clang would reject it, saying the evaluation of `C<T>` depends on itself. GCC would reject it if # 1 is a template, while it would accept it if # 1 is a non-template.
It appears that two compilers disagree on when the circular dependency check will happen. For GCC, non-templates seem to have a higher priority over the template argument deduction and hence it would accept the case speculatively.
The other issue exposed by my approach of CWG2369 is, for a similar case below:
```cpp
template <class Tp>
concept partially_ordered_with = requires(Tp t, Tp u) { t <= u; };
struct time_point {};
struct leap_second {};
auto operator<=>(time_point, time_point) { return 1; } // #1
template <class Duration>
requires partially_ordered_with<Duration>
auto operator<=>(leap_second, Duration); // #2
time_point process_end;
bool result = process_end >= process_end;
```
Clang currently accepts it, while this won't be the case with my patch because we try to pick up the best candidate while evaluating the constraint `t <= u`, and while checking # 2, it would be a substitution failure rather than a hard error because the function template substitution happens before the constraint evaluation. My patch swapped their orders, and therefore we would evaluate the constraint on # 2 again, hence a self-dependent error.
As exhibited above, it is unclear to us whether we should accept the non-template early so we could avoid some cases that would otherwise result in a self-dependent error.
CC @zygoloid @cor3ntin for some insights.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykVk1v4zgM_TXKhWjgyEmaHHJok81gsJjTBNhjIctMrK0iaSU5rvvrF5Qdx_2YD-wCRYtaIvlI8T1ShKBOBnHDFo9ssZuIOlbWb15bk_HZ_aSwZbs5VCpAIwLURtoLeiyhqZRG-Jq-NtY_K3MCayBWCOrsNJ7RRBGVNWCPsP3rC8-Xa1AGqhhdYPkD43vG9ycVq7qYSntmfK_15frnznn7N8rI-F6FUGNgfL-Yz-cZyx_hK3hhQJloQYBWhXx5gYghgseTxxCUNYxvQZgSYiVid3YUStceIdbeYAm2jhAtFAgCShWkRyeMbAnhxxSmLNux7KH7fagQnMc7fFEhUtYJIKgAIsDRam2bAIyvYiXMc6AgbJ5J63MTlYGmslChdljSyVGZHkqFYGphJIKQ3oYAX7ZdBlstzInxNZVshIIts-5HOjf-HvHstIgILN9KLUKAg2P5H92htEaii7AFlu_A4z-18lTa1cFBZHwN7P4RjoQ9BXwEdr9j-ePYf4i-lhG-09WPp92jwhhEbB0acUY4pKAXq8oBj6ipBoyvvl-De6T3gVkfHHqHjOezX2Q5OB3ygi3Lt4ePwQ7X5AbffOz7O7ghK2UiqISbDF1n-OkzvK3C6l2XSzk92bKwOk6tPzG-f2V8f_m2nL28FH--ktuR-Q6DUxGhqTBW6AkgzFJ_DYWl9k6NAY2tdQkeiSygIh0E0VJbUkvhReh6YCFbZkNJlhmU6NCUgVirYkB9nKame-cR1PFHCDoJULE3ETI11wcTY83d1ewNk75GEM6h8KHnaWNB2rNTGn0gVoqTRyR8TYUdL6XystbC9-CRKCsrlM_QKK2hIn9mCnvrKRcCOY4eICCeiXiVuBDzK3WiCjuvrFexBdK2FGdoMOFPNekAlFjWMlWSWFkhUfV96gmhCAjBIcGM6oK6_aAeNj1rJxv44mzAEooWzi2Vw1shqzeaGSiNo_UgIKizouxTkAK1bX4pC78lCE74qITW7ZP1Jcn7U6Ni9blKbOHgoL4SNpJfulf_VC-iOuOTs8Snd8LRX9Ao3FNAaU35ubQk-lqHXkTru5iUBl_dXBO28X__U1J2tU_UuSnLTVo-LxjLtx-Mfoh7lDEBHwx_Kk6jOjpvJYbwhKYcSlVYq8FjqHVMjze6AxT17adbhT9TsU5fZO09mqjbvsdDLzId92PaCwj0faRZOhAgtc-5BSeirKBAKWr6ihB9S_xzSj5D7ZJBQeNZClOqUiTZI89X5eqFTFoTohepf5bZqOmW2XXUd3ZJDMiKBIjT2UDSNOtDXYSoYp2YfN0JvEiMpIlNoiB8Cei99QNwgnCsTcf_oVPe-OqkJ0CBR-vxPeibEE_h27UsoSEbWlJQeUiNFG6LC_rOU4M9_t7HB9_WdMmCOAmVNp9OnQSQqN9dlTJ2Ob1Ro4cA-FKpQkUsQRT2gn3FVFr1NApPr1WHYRg1CKF6r3ljjQUUXrcQLF2V3U0a-hDsuWuOXu27pJIWNirgtW2V-R3g2y1tVa_tyWryPd6wSClTLGWCOlUxTCflJi_X-VpMcDO75_lqtljMZpNqk5fZfFGs-DqTa5TlrJzP-RGl5LN1WUiUE7XhGZ9nq9lyluerfDbNF3m2lvkyK45ZOeeczTM8C6WntLTSbJ8kWd_MsvlizSdaFKhD2qw5l2mTyx-O3ppI9OPUn3TQqXCgD4vdxG_SBlzUp8DmmVYhhpv7qKJOq3rnbbEDmihRndP-fbz1__XBxLhVVHhf2ttDT2qvN_99O-8zvmz4vwEAAP__8qf5cQ">