microsoft / microsoft/STL

`<xutility>`: concept failed constraint has poor diagnostics.

Open
#2,648 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement ranges
Dominant language
C++
Stars
11.1k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

For the following code:
https://godbolt.org/z/vYcqsW5qx

#include <algorithm>
#include <iterator>
#include <ranges>

struct it {
    it() noexcept;
    it &operator++() noexcept;
    it operator++(int) noexcept;
    int *operator*() const noexcept;
    int *operator->() const noexcept;
    bool operator==(const it &it) const noexcept;
    bool operator!=(const it &it) const noexcept;
};

template <typename T>
struct adapter {
    it begin() const;
    it end() const;
};

template <class T>
constexpr bool std::ranges::enable_borrowed_range<adapter<T>> = true;

using collection = adapter<int>;

bool pred(int *pdod) noexcept;

template <typename Col, typename Pred>
bool any_of_wrapper(Col &&col, Pred pred) {
    return std::any_of(col.begin(), col.end(), pred);
}

void cpp17() { std::begin(collection()); }
void cpp20() { std::ranges::begin(collection()); }

MSVC does not emit concepts diagnostics, so this bug report focuses on clang.

Using the Microsoft STL I see:

a.cpp(26,16): warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result]
void cpp17() { std::begin(collection()); }
               ^~~~~~~~~~ ~~~~~~~~~~~~
a.cpp(27,16): error: no matching function for call to object of type 'const _Begin::_Cpo'
void cpp20() { std::ranges::begin(collection()); }
               ^~~~~~~~~~~~~~~~~~
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\xutility(2023,39): note: candidate template ignored: constraints not satisfied
      [with _Ty = adapter<int>]
            _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept(_Choice<_Ty&>._No_throw) {
                                      ^
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.31.31103\include\xutility(2022,27): note: because '_Choice<adapter<int> &>._Strategy != _St::_None'
      evaluated to false
                requires (_Choice<_Ty&>._Strategy != _St::_None)
                          ^
1 warning and 1 error generated.

The way the Microsoft STL is written the diagnostic is not useful. I have to look at the code and even then it does not tell me what the issue is.

If use the GCC STL I see:

<source>:34:16: error: no matching function for call to object of type 'const __cust_access::_Begin'
void cpp20() { std::ranges::begin(collection()); }
               ^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:114:2: note: candidate template ignored: constraints not satisfied [with _Tp = adapter<int>]
        operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
        ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:111:11: note: because 'is_array_v<remove_reference_t<adapter<int> > >' evaluated to false
        requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
                 ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:111:50: note: and 'adapter<int>' does not satisfy '__member_begin'
        requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
                                                        ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:947:6: note: because 'decay_t<it>' (aka 'it') does not satisfy 'input_or_output_iterator':
          { __decay_copy(__t.begin()) } -> input_or_output_iterator;
            ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:616:5: note: because 'it' does not satisfy 'weakly_incrementable'
        && weakly_incrementable<_Iter>;
           ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:207:7: note: because 'typename iter_difference_t<_Iter>' would be invalid: no type named 'difference_type' in 'std::incrementable_traits<it>'
      using __iter_diff_t = typename
      ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/ranges_base.h:112:7: note: and 'adapter<int>' does not satisfy '__adl_begin'
          || __adl_begin<_Tp>
             ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.1/../../../../include/c++/12.0.1/bits/iterator_concepts.h:958:19: note: because '__decay_copy(begin(__t))' would be invalid: call to deleted function 'begin'
          { __decay_copy(begin(__t)) } -> input_or_output_iterator;
                         ^
1 error generated.

Which gives me a clear pointer of what failed.

Would it be possible to refactor the code in xutility related to ranges::begin constraints so that the compiler is able to emit proper constraints diagnostics?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue points to ranges::begin constraints in xutility; start there and compare the reported MSVC and GCC diagnostics. Refactor that area so a failing iterator constraint is surfaced directly in clang diagnostics, then verify the example reports the missing requirement rather than only a failed aggregate constraint.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
developer-experience
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.