<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/62943>62943</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[c++20][Modules] incorrect error regarding ambiguous specialization
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang:frontend,
clang:modules
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
ChuanqiXu9
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
mordante
</td>
</tr>
</table>
<pre>
Tested with a recent clang nightly build, using libc++'s `std` module.
https://github.com/llvm/llvm-project/blob/11ea40cff5413057d823a4b3ac5ac419b674dc56/libcxx/include/__iterator/readable_traits.h#L84
```
template <class _Ip>
using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,
indirectly_readable_traits<remove_cvref_t<_Ip> >,
iterator_traits<remove_cvref_t<_Ip> > >::value_type;
```
Here the `indirectly_readable_traits` causes an ambiguous specialization error in the following code:
```
import std;
template <class It>
class contiguous_iterator {
It it_;
public:
typedef std::contiguous_iterator_tag iterator_category;
typedef typename std::iterator_traits<It>::value_type value_type;
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef It pointer;
typedef typename std::iterator_traits<It>::reference reference;
typedef typename std::remove_pointer<It>::type element_type;
constexpr It base() const { return it_; }
constexpr contiguous_iterator() : it_() {}
constexpr explicit contiguous_iterator(It it) : it_(it) {}
constexpr reference operator*() const { return *it_; }
constexpr pointer operator->() const { return it_; }
constexpr reference operator[](difference_type n) const { return it_[n]; }
constexpr contiguous_iterator& operator++() {
++it_;
return *this;
}
constexpr contiguous_iterator& operator--() {
--it_;
return *this;
}
constexpr contiguous_iterator operator++(int) { return contiguous_iterator(it_++); }
constexpr contiguous_iterator operator--(int) { return contiguous_iterator(it_--); }
constexpr contiguous_iterator& operator+=(difference_type n) {
it_ += n;
return *this;
}
constexpr contiguous_iterator& operator-=(difference_type n) {
it_ -= n;
return *this;
}
friend constexpr contiguous_iterator operator+(contiguous_iterator x, difference_type n) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator+(difference_type n, contiguous_iterator x) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator-(contiguous_iterator x, difference_type n) {
x -= n;
return x;
}
friend constexpr difference_type operator-(contiguous_iterator x, contiguous_iterator y) { return x.it_ - y.it_; }
friend constexpr bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ == y.it_;
}
friend constexpr bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ != y.it_;
}
friend constexpr bool operator<(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ < y.it_; }
friend constexpr bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ <= y.it_;
}
friend constexpr bool operator>(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ > y.it_; }
friend constexpr bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ >= y.it_;
}
};
using ContiguousIter = contiguous_iterator<const int*>;
// enabling this "fixes" the issue.
//static_assert(std::same_as<std::indirectly_readable_traits<float*>::value_type, float>);
static_assert(std::contiguous_iterator<ContiguousIter>);
```
This code is reduced from the `ranges::data` test. The interesting part is when the `indirectly_readable_traits` is used in a `static_assert` for an unrelated type, then the code compiles. When using this code without modules it works too.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzEWF1z6jYQ_TXiRQNjJJuPBx6IE6aZad_uTPvmkaUF1MqSK8kJ9Nd3ZBvzETuXJPe2M4RgZJ09e_YYe5c5J3caYIWSB0RIuq-Y_lv-US0RISh5HLHK741dFcYKpj2MciOOq2_gPAj8Kv0eM2yBg_aYK6Z3WMvd3qsjziupBCIprpzUO6xkzhF5qF9zh9Escl6gWYQLIyoFExQ9omjdvO-9Lx2ia0Q2iGx20u-rfMJNgchGqZfTv3FpzZ_APSKbXJkckc10CiyO-HabxFMaJXOxIJTFOWU8YTyeLvPZPBY8mQUAmfPDAZGN1FxVAhDZZJn0YJk3FpGNBSZYriDzlknvJntE6K-LuGU5i9pXfeihKBXzgBFNuWLO4ey5RPSpWW3SD9DZC1MVZB4j-oj9sQTNCsDcaCG9NJqpzCOaZpl0WWllwewxO0Ejmp7ItYwQTS0U5gUy_mJh22ytw-L2LwhI13VMRNKGDJZaSAvcq2N2k-L7gBcIX-CRhawRfeiVsXn_BSxgv4fgkHfIziLMWeXAYaYxK3K5q0zlsCuBS6bkPywoisFaY7HUNeDWKGVeQzG4ERBY9bGQRWmsx8GcHc-BKj_7rsjNF9xo3xDprITRvEXB-Nlj6bMOtqxyJXnHA9eWELBtYgfNevAyz3bnEnDmYWfsscM8g3T-6tDeFq5J4KY8uKdSn4YVcrsFC5q32DfHPQGePS6N1B7s16NbaIPh7tNdoK2hOx6XmHUaoKAA7W_s3OJyo52HQ2lDLjlzgMgCkWXzffADtuArq1szYDR_HALoMUALhui63t8ezR86lIvtcCiV5NIP4NR-vAZrjy_g3oCeRTXlCWo9lCIi69ssL_NrFe6QxvUvzX1q4fc5JQ8oeURkcetAPQiePOiw5RMVmV1I0dzhuqq0ABg3K5fXf_j2LJPfS3de6s3yO7HH47644_FVzKGAd0d8m6rUJ9Oc0PvtVjus2bMcrOR7EesEPxAtnL_8ej3poI2uhJY-w83pWP9Ava8q_BEu4xsm97ltayVo8RELLPrOOIQHv-_zPPQoduZ56JfrExR7mKS92w7_A8XxVzUcrvS99G6j3EWtb-F4c20eJrUV8XEydLN7wyU3Rp3LRx8bzze_2APXx4nO8BnHN7JdEWzCdCzvkeyaJpn-DJrXHOsYX-BI0x9H8Fa-tKfC9xD6T2qbflG3p5-n29OndHv6-WarYwyLFj5cP_c2bW7ahXoOz3UBoy86TRtm9c18XQe7Amsafwya5SrAhtsVRoRs5QEcIqTu56RzVTc3qDc4z7zkGXMOrEdk0T3QO1ZAxkJ3cG4c3muEt8qwjtlN90pS3CwHXyw74oOx-_O_FuoG66Yl_RayDz0rlg5bEBUHgbfWFKc-2TK9A9d2XMyz0B17cH6CvwWdwiM2OB-ELJn1AeV1D_q-Lls6XDkQoYlmzdTmMs9ZhLfGhh680hZCeyzwSSV_ilFT56YopQI3wfj3sND4xXepvUq_N5Vvx0EOS49fjf3LYW_MZCRWVCzpko1gNZ0tkoguFzEd7VdCJNE2ingex0si5tMl5XOI43yazISY59ORXJGI0CghyXRB54ROEkgivkimhCU0jmGJ4ggKJtVEqZdiYuxuVPtqNSPLmI4Uy0G5djRWz7cQXW-t0R60QIQgkl4stNzbwZld1VOqvNo5FEdKOu_OQbz0qh65tUMxEoXeI3n4rYVIHrHU3NhQmHaMYWHHrAiqDc07RpVVqw8Pz-p8HSKbOuV_AwAA__-tiXES">