[libcxx-commits] [clang] [libcxx] [Clang] Normalize constraints before checking for satisfaction (PR #161671)

Lei Wang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 6 14:36:10 PDT 2025


wlei-llvm wrote:

> @wlei-llvm We would appreciate it if you can provide us with a self-contained reproducer, otherwise there's nothing we can do.

Hi @zyn0217 , here is a reproducer:

test.cpp:
```
#include <range/v3/view.hpp>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/iota.hpp>

void foo() {
    std::vector<int>  a = ranges::views::iota(0, 1)
           | ranges::to_vector;

    std::vector<int> b = ranges::views::iota(0, 1)
         | ranges::views::filter([&](const auto& col) { return true; }) 
         | ranges::to_vector;
}
  
```
And it can be reproduced by the `range-v3` truck: https://github.com/ericniebler/range-v3

Cmd:
```
clang++ test.cpp -I range-v3/include/  -std=c++20  -c
```
Error:

```
In file included from test.cpp:3:
In file included from range-v3/include/range/v3/view.hpp:17:
In file included from range-v3/include/range/v3/view/adaptor.hpp:28:
In file included from range-v3/include/range/v3/view/all.hpp:26:
In file included from range-v3/include/range/v3/view/ref.hpp:25:
range-v3/include/range/v3/view/interface.hpp:233:59: error: invalid operands to binary expression ('detail::facade_sentinel_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>>' (aka 'ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>>') and 'detail::facade_iterator_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>>' (aka 'basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>>'))
  233 |             return static_cast<size_type>(derived().end() - derived().begin());
      |                                           ~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~
range-v3/include/range/v3/range/primitives.hpp:138:35: note: in instantiation of function template specialization 'ranges::view_interface<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>>::size<true>' requested here
  138 |                 return ((R &&) r).size();
      |                                   ^
range-v3/include/range/v3/range/conversion.hpp:325:39: note: in instantiation of function template specialization 'ranges::_size_::fn::operator()<ranges::filter_view<ranges::iota_view<int, int>, (lambda at test.cpp:14:34)> &>' requested here
  325 |                 auto const rng_size = ranges::size(rng);
      |                                       ^
range-v3/include/range/v3/range/conversion.hpp:346:24: note: in instantiation of function template specialization 'ranges::detail::to_container::fn<ranges::detail::from_range<std::vector>>::impl<std::vector<int>, ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>>, ranges::filter_view<ranges::iota_view<int, int>, (lambda at test.cpp:14:34)>>' requested here
  346 |                 return impl<cont_t, iter_t>(static_cast<Rng &&>(rng), use_reserve_t{});
      |                        ^
range-v3/include/range/v3/range/conversion.hpp:276:24: note: in instantiation of function template specialization 'ranges::detail::to_container::fn<ranges::detail::from_range<std::vector>>::operator()<ranges::filter_view<ranges::iota_view<int, int>, (lambda at test.cpp:14:34)>>' requested here
  276 |                 return static_cast<Fn &&>(fn)(static_cast<Rng &&>(rng));
      |                        ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:803:5: note: candidate template ignored: constraints not satisfied [with Cur = ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>]
  803 |     operator-(basic_iterator<Cur> left, typename basic_iterator<Cur>::difference_type n)
      |     ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:801:18: note: because 'ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>' does not satisfy 'random_access_cursor'
  801 |         requires detail::random_access_cursor<Cur>)
      |                  ^
range-v3/include/range/v3/detail/prologue.hpp:35:26: note: expanded from macro 'template'
   35 |     template<__VA_ARGS__ CPP_TEMPLATE_AUX_                                      \
      |                          ^
range-v3/include/range/v3/detail/range_access.hpp:378:13: note: because 'sized_sentinel_for_cursor<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  378 |             sized_sentinel_for_cursor<T, T> && //
      |             ^
range-v3/include/range/v3/detail/range_access.hpp:329:30: note: because 'detail::sized_sentinel_for_cursor_requires_<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  329 |             CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
      |                              ^
range-v3/include/range/v3/detail/range_access.hpp:319:17: note: because 'range_access::distance_to(c, s) , concepts::requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>' would be invalid: no matching function for call to 'distance_to'
  319 |                 range_access::distance_to(c, s),
      |                 ^
range-v3/include/range/v3/detail/range_access.hpp:319:17: note: and 'range_access::distance_to(c, s) , concepts::requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>' would be invalid: no matching function for call to 'distance_to'
range-v3/include/range/v3/detail/range_access.hpp:329:30: note: and 'detail::sized_sentinel_for_cursor_requires_<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  329 |             CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
      |                              ^
range-v3/include/range/v3/detail/range_access.hpp:319:17: note: because 'range_access::distance_to(c, s) , concepts::requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>' would be invalid: no matching function for call to 'distance_to'
  319 |                 range_access::distance_to(c, s),
      |                 ^
range-v3/include/range/v3/detail/range_access.hpp:319:17: note: and 'range_access::distance_to(c, s) , concepts::requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>' would be invalid: no matching function for call to 'distance_to'
range-v3/include/range/v3/iterator/basic_iterator.hpp:811:5: note: candidate template ignored: constraints not satisfied [with Cur2 = ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>, Cur = ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>]
  811 |     operator-(basic_iterator<Cur2> const & left, basic_iterator<Cur> const & right)
      |     ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:809:18: note: because 'detail::sized_sentinel_for_cursor<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  809 |         requires detail::sized_sentinel_for_cursor<Cur2, Cur>)
      |                  ^
range-v3/include/range/v3/detail/prologue.hpp:35:26: note: expanded from macro 'template'
   35 |     template<__VA_ARGS__ CPP_TEMPLATE_AUX_                                      \
      |                          ^
range-v3/include/range/v3/detail/range_access.hpp:329:30: note: because 'detail::sized_sentinel_for_cursor_requires_<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  329 |             CPP_requires_ref(detail::sized_sentinel_for_cursor_, S, C);
      |                              ^
range-v3/include/range/v3/detail/range_access.hpp:319:17: note: because 'range_access::distance_to(c, s) , concepts::requires_<signed_integer_like_<decltype(range_access::distance_to(c, s))>>' would be invalid: no matching function for call to 'distance_to'
  319 |                 range_access::distance_to(c, s),
      |                 ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:819:5: note: candidate template ignored: constraints not satisfied [with S = detail::facade_sentinel_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>>, Cur = ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>]
  819 |     operator-(S const & left, basic_iterator<Cur> const & right)
      |     ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:817:18: note: because 'detail::sized_sentinel_for_cursor<detail::facade_sentinel_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> > >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  817 |         requires detail::sized_sentinel_for_cursor<S, Cur>)
      |                  ^
range-v3/include/range/v3/detail/prologue.hpp:35:26: note: expanded from macro 'template'
   35 |     template<__VA_ARGS__ CPP_TEMPLATE_AUX_                                      \
      |                          ^
range-v3/include/range/v3/detail/range_access.hpp:328:13: note: because 'sentinel_for_cursor<ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor> >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  328 |             sentinel_for_cursor<S, C> &&
      |             ^
range-v3/include/range/v3/detail/range_access.hpp:271:30: note: because 'detail::sentinel_for_cursor_requires_<ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor> >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  271 |             CPP_requires_ref(detail::sentinel_for_cursor_, S, C);
      |                              ^
range-v3/include/range/v3/detail/range_access.hpp:261:17: note: because 'range_access::equal(c, s) , concepts::requires_<convertible_to<decltype(range_access::equal(c, s)), bool>>' would be invalid: no matching function for call to 'equal'
  261 |                 range_access::equal(c, s),
      |                 ^
range-v3/include/range/v3/detail/range_access.hpp:261:17: note: and 'range_access::equal(c, s) , concepts::requires_<convertible_to<decltype(range_access::equal(c, s)), bool>>' would be invalid: no matching function for call to 'equal'
range-v3/include/range/v3/iterator/basic_iterator.hpp:826:5: note: candidate template ignored: constraints not satisfied [with Cur = ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>::adaptor>, S = detail::facade_iterator_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)>>>]
  826 |     operator-(basic_iterator<Cur> const & left, S const & right)
      |     ^
range-v3/include/range/v3/iterator/basic_iterator.hpp:824:18: note: because 'detail::sized_sentinel_for_cursor<detail::facade_iterator_t<ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> > >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  824 |         requires detail::sized_sentinel_for_cursor<S, Cur>)
      |                  ^
range-v3/include/range/v3/detail/prologue.hpp:35:26: note: expanded from macro 'template'
   35 |     template<__VA_ARGS__ CPP_TEMPLATE_AUX_                                      \
      |                          ^
range-v3/include/range/v3/detail/range_access.hpp:328:13: note: because 'sentinel_for_cursor<ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor> >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  328 |             sentinel_for_cursor<S, C> &&
      |             ^
range-v3/include/range/v3/detail/range_access.hpp:271:30: note: because 'detail::sentinel_for_cursor_requires_<ranges::basic_iterator<ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor> >, ranges::adaptor_cursor<ranges::basic_iterator<ranges::iota_view<int, int>::cursor>, ranges::remove_if_view<ranges::iota_view<int, int>, ranges::logical_negate<(lambda at test.cpp:14:34)> >::adaptor>>' evaluated to false
  271 |             CPP_requires_ref(detail::sentinel_for_cursor_, S, C);
      |                              ^
range-v3/include/range/v3/detail/range_access.hpp:261:17: note: because 'range_access::equal(c, s) , concepts::requires_<convertible_to<decltype(range_access::equal(c, s)), bool>>' would be invalid: no matching function for call to 'equal'
  261 |                 range_access::equal(c, s),
      |                 ^
range-v3/include/range/v3/detail/range_access.hpp:261:17: note: and 'range_access::equal(c, s) , concepts::requires_<convertible_to<decltype(range_access::equal(c, s)), bool>>' would be invalid: no matching function for call to 'equal'
range-v3/include/range/v3/iterator/common_iterator.hpp:290:27: note: candidate template ignored: could not match 'common_iterator' against 'ranges::basic_iterator'
  290 |     iter_difference_t<I2> operator-(common_iterator<I1, S1> const & x,
      |                           ^
range-v3/include/range/v3/iterator/counted_iterator.hpp:377:37: note: candidate template ignored: could not match 'counted_iterator' against 'ranges::basic_iterator'
  377 |     constexpr iter_difference_t<I2> operator-(counted_iterator<I1> const & x,
      |                                     ^
range-v3/include/range/v3/iterator/counted_iterator.hpp:384:36: note: candidate template ignored: could not match 'counted_iterator' against 'ranges::basic_iterator'
  384 |     constexpr iter_difference_t<I> operator-(counted_iterator<I> const & x,
      |                                    ^
range-v3/include/range/v3/iterator/counted_iterator.hpp:391:36: note: candidate template ignored: could not match 'counted_iterator' against 'basic_iterator'
  391 |     constexpr iter_difference_t<I> operator-(default_sentinel_t,
      |                                    ^
1 error generated.
```


Thanks!



https://github.com/llvm/llvm-project/pull/161671


More information about the libcxx-commits mailing list