Skip to content
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

[c++20][Modules] incorrect error regarding ambiguous specialization #62943

Closed
mordante opened this issue May 25, 2023 · 8 comments
Closed

[c++20][Modules] incorrect error regarding ambiguous specialization #62943

mordante opened this issue May 25, 2023 · 8 comments
Assignees
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules

Comments

@mordante
Copy link
Member

mordante commented May 25, 2023

Tested with a recent Clang nightly build, using libc++'s std module.

using iter_value_t = typename conditional_t<__is_primary_template<iterator_traits<remove_cvref_t<_Ip> > >::value,

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.

@mordante mordante added clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels May 25, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented May 25, 2023

@llvm/issue-subscribers-clang-modules

@llvmbot
Copy link
Collaborator

llvmbot commented May 25, 2023

@llvm/issue-subscribers-clang-frontend

@ChuanqiXu9
Copy link
Member

Given it is a little little bit hard to play around std modules now, I'd like to investigate the issue several weeks later.

@mordante
Copy link
Member Author

That sounds sensible to me.

@mordante
Copy link
Member Author

mordante commented Jun 1, 2023

I've create a patch for module support https://reviews.llvm.org/D151814 you could test with that patch or wait until it lands.

@ChuanqiXu9
Copy link
Member

I've create a patch for module support https://reviews.llvm.org/D151814 you could test with that patch or wait until it lands.

I'd like to wait for it lands. Since I am looking at support modules in clangd recently: clangd/clangd#1293. I feel it may be less overhead to test this after it lands.

@ChuanqiXu9
Copy link
Member

I got the problem. It is much more complex than I thought. I sent a mail to WG21. If you're interested, you can take a look at EWG/CWG's mailing list.

@mordante
Copy link
Member Author

Thanks for the notification! I'm not subscribed to these lists, but I'll look in the archives.

veselypeta pushed a commit to veselypeta/cherillvm that referenced this issue Aug 29, 2024
…traints

Close llvm/llvm-project#62943.

The root cause for the issue is that we think the associated constraints
from the 'same' declaration in different module units are different
incorrectly. Since the constraints doesn't know anything about decls and
modules, we should fix the problem by getting the associated constraints
from the exactly the same declarations from different modules.
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" clang:modules C++20 modules and Clang Header Modules
Projects
None yet
Development

No branches or pull requests

3 participants