https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120934

            Bug ID: 120934
           Summary: views::concat is ill-formed depending on argument
                    order
           Product: gcc
           Version: 15.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: francois.hamonic at gmail dot com
  Target Milestone: ---

The following example will fail to compile due to `std::views::concat(r2, r1)`
iterators not satisfying `equality_comparable` while `std::views::concat(r1,
r2)` is fine.

The same behavior has been observed on all recent GCC implementations I tested
(local GCC 15.1.0 and Godbolt GCC 15.1 and 16.0 trunk).
The following error message is produced by https://godbolt.org/z/ac5jKe4Gr (GCC
16.0.0 20250702 (experimental) with ` -Wall -Wextra -std=c++26
-fconcepts-diagnostics-depth=5`).

Example :

#include <ranges>
#include <vector>

int main() {
    auto r1 = std::views::single(1);
    std::vector<int> vec = {2, 3};
    auto r2 = std::views::join(std::views::transform(vec, std::views::single));

    auto c1 = std::views::all(std::views::concat(r1, r2)); // OK
    auto c2 = std::views::all(std::views::concat(r2, r1)); // not OK
}

Error message :

<source>: In function 'int main()':
<source>:10:30: error: no match for call to '(const std::ranges::views::_All)
(std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >)'
   10 |     auto c2 = std::views::all(std::views::concat(r2, r1)); // not OK
      |               ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from <source>:1:
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:1429:12:
note: there is 1 candidate
 1429 |     struct _All : __adaptor::_RangeAdaptorClosure<_All>
      |            ^~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:1448:9:
note: candidate 1: 'template<class _Range>  requires (viewable_range<_Range>)
&& ((view<typename std::decay<_Tp>::type>) || (__can_ref_view<_Range>) ||
(__can_owning_view<_Range>)) constexpr auto
std::ranges::views::_All::operator()(_Range&&) const'
 1448 |         operator() [[nodiscard]] (_Range&& __r) const
      |         ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:1448:9:
note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:1448:9:
note: constraints not satisfied
In file included from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/string_view:58,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/basic_string.h:51,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/string:56,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/locale_classes.h:42,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ios_base.h:43,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/streambuf:45,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/streambuf_iterator.h:37,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/iterator:68,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:45:
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:
In substitution of 'template<class _Range>  requires (viewable_range<_Range>)
&& ((view<typename std::decay<_Tp>::type>) || (__can_ref_view<_Range>) ||
(__can_owning_view<_Range>)) constexpr auto
std::ranges::views::_All::operator()(_Range&&) const [with _Range =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]':
<source>:10:30:   required from here
   10 |     auto c2 = std::views::all(std::views::concat(r2, r1)); // not OK
      |               ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:514:13:
  required for the satisfaction of 'range<_Tp>' [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:831:13:
  required for the satisfaction of 'viewable_range<_Range>' [with _Range =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:514:21:
  in requirements with '_Tp& __t' [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:517:20:
note: the required expression 'std::ranges::_Cpo::end(__t)' is invalid, because
  517 |         ranges::end(__t);
      |         ~~~~~~~~~~~^~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:517:20:
error: no match for call to '(const std::ranges::__access::_End)
(std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&)'
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:162:12:
note: there is 1 candidate
  162 |     struct _End
      |            ^~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:182:9:
note: candidate 1: 'template<class _Tp>  requires (__maybe_borrowed_range<_Tp>)
&& ((is_bounded_array_v<typename std::remove_reference<_Tp>::type>) ||
(__member_end<_Tp>) || (__adl_end<_Tp>)) constexpr auto
std::ranges::__access::_End::operator()(_Tp&&) const'
  182 |         operator()[[nodiscard]](_Tp&& __t) const
noexcept(_S_noexcept<_Tp&>())
      |         ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:182:9:
note: template argument deduction/substitution failed:
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:182:9:
note: constraints not satisfied
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:
In substitution of 'template<class _Tp>  requires (__maybe_borrowed_range<_Tp>)
&& ((is_bounded_array_v<typename std::remove_reference<_Tp>::type>) ||
(__member_end<_Tp>) || (__adl_end<_Tp>)) constexpr auto
std::ranges::__access::_End::operator()(_Tp&&) const [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]':
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:517:13:
  required by substitution of 'template<class _Range>  requires
(viewable_range<_Range>) && ((view<typename std::decay<_Tp>::type>) ||
(__can_ref_view<_Range>) || (__can_owning_view<_Range>)) constexpr auto
std::ranges::views::_All::operator()(_Range&&) const [with _Range =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]'
  517 |         ranges::end(__t);
      |         ~~~~~~~~~~~^~~~~
<source>:10:30:   required from here
   10 |     auto c2 = std::views::all(std::views::concat(r2, r1)); // not OK
      |               ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:182:2:
  required by the constraints of 'template<class _Tp>  requires
(__maybe_borrowed_range<_Tp>) && ((is_bounded_array_v<typename
std::remove_reference<_Tp>::type>) || (__member_end<_Tp>) || (__adl_end<_Tp>))
constexpr auto std::ranges::__access::_End::operator()(_Tp&&) const'
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:180:32:
note: no operand of the disjunction is satisfied
  179 |         requires is_bounded_array_v<remove_reference_t<_Tp>>
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  180 |           || __member_end<_Tp> || __adl_end<_Tp>
      |           ~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:179:18:
note: the operand 'is_bounded_array_v<typename
std::remove_reference<_Tp>::type>' is unsatisfied because
  179 |         requires is_bounded_array_v<remove_reference_t<_Tp>>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  180 |           || __member_end<_Tp> || __adl_end<_Tp>
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:182:2:
  required by the constraints of 'template<class _Tp>  requires
(__maybe_borrowed_range<_Tp>) && ((is_bounded_array_v<typename
std::remove_reference<_Tp>::type>) || (__member_end<_Tp>) || (__adl_end<_Tp>))
constexpr auto std::ranges::__access::_End::operator()(_Tp&&) const'
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:179:18:
note: the expression 'is_bounded_array_v<typename
std::remove_reference<_Tp>::type> [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]' evaluated to 'false'
  179 |         requires is_bounded_array_v<remove_reference_t<_Tp>>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:180:14:
note: the operand '__member_end<_Tp>' is unsatisfied because
  179 |         requires is_bounded_array_v<remove_reference_t<_Tp>>
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  180 |           || __member_end<_Tp> || __adl_end<_Tp>
      |           ~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/version.h:51,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:38,
                 from
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:39:
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:147:15:
  required for the satisfaction of '__member_end<_Tp>' [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:147:30:
  in requirements with '_Tp& __t' [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:149:13:
note: '(auto)(__t.end())' does not satisfy return-type-requirement, because
  149 |           { _GLIBCXX_AUTO_CAST(__t.end()) } ->
sentinel_for<__range_iter_t<_Tp>>;
      |             ^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:149:13:
error: deduced expression type does not satisfy placeholder constraints
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:149:13:
note: constraints not satisfied
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:304:15:  
required for the satisfaction of '__weakly_eq_cmp_with<_Sent, _Iter>' [with
_Sent =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false>; _Iter =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false>]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/iterator_concepts.h:676:13:
  required for the satisfaction of 'sentinel_for<decltype(auto) [requires
std::sentinel_for<<placeholder>,
decltype(std::ranges::__access::__begin((declval<_Container&>)()))>], decltype
(std::ranges::__access::__begin(declval<_Container&>()))>' [with decltype(auto)
[requires std::sentinel_for<<placeholder>,
decltype(std::ranges::__access::__begin((declval<_Container&>)()))>] =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false>; _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:305:4:  
in requirements with 'std::remove_reference_t<_Tp>& __t',
'std::remove_reference_t<_Rhs>& __u' [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false>; _Up =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false>]
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:306:17:
note: the required expression '(__t == __u)' is invalid, because
  306 |           { __t == __u } -> __boolean_testable;
      |             ~~~~^~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:306:17:
error: no match for 'operator==' (operand types are
'std::remove_reference_t<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >' {aka 'const
std::remove_reference<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >::type'} and
'std::remove_reference_t<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >' {aka 'const
std::remove_reference<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >::type'})
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:306:17:
note: there are 2 candidates
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10052:5:
note: candidate 1: 'constexpr bool std::ranges::operator==(const
concat_view<join_view<transform_view<ref_view<std::vector<int,
std::allocator<int> > >, views::_Single> >, single_view<int>
>::_Iterator<false>&, std::default_sentinel_t)' (reversed)
10052 |     operator==(const _Iterator& __it, default_sentinel_t)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10052:39:
note: no known conversion for argument 2 from
'std::remove_reference_t<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >' {aka 'const
std::remove_reference<std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >::_Iterator<false> >::type'} to
'std::default_sentinel_t'
10052 |     operator==(const _Iterator& __it, default_sentinel_t)
      |                                       ^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10043:5:
note: candidate 2: 'constexpr bool std::ranges::operator==(const
concat_view<join_view<transform_view<ref_view<std::vector<int,
std::allocator<int> > >, views::_Single> >, single_view<int>
>::_Iterator<false>&, const
concat_view<join_view<transform_view<ref_view<std::vector<int,
std::allocator<int> > >, views::_Single> >, single_view<int>
>::_Iterator<false>&) requires
(equality_comparable<decltype(std::ranges::__access::__begin((declval<typename
std::__conditional<_Const>::type<const _Vs, _Vs>&>)()))> && ...)'
10043 |     operator==(const _Iterator& __x, const _Iterator& __y)
      |     ^~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10043:5:
note: constraints not satisfied
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges: In
instantiation of 'constexpr bool std::ranges::operator==(const
concat_view<join_view<transform_view<ref_view<std::vector<int,
std::allocator<int> > >, views::_Single> >, single_view<int>
>::_Iterator<false>&, const
concat_view<join_view<transform_view<ref_view<std::vector<int,
std::allocator<int> > >, views::_Single> >, single_view<int>
>::_Iterator<false>&) requires
(equality_comparable<decltype(std::ranges::__access::__begin((declval<typename
std::__conditional<_Const>::type<const _Vs, _Vs>&>)()))> && ...)':
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/concepts:306:10:  
required by substitution of 'template<class _Tp>  requires
(__maybe_borrowed_range<_Tp>) && ((is_bounded_array_v<typename
std::remove_reference<_Tp>::type>) || (__member_end<_Tp>) || (__adl_end<_Tp>))
constexpr auto std::ranges::__access::_End::operator()(_Tp&&) const [with _Tp =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >&]'
  306 |           { __t == __u } -> __boolean_testable;
      |             ~~~~^~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/bits/ranges_base.h:517:13:
  required by substitution of 'template<class _Range>  requires
(viewable_range<_Range>) && ((view<typename std::decay<_Tp>::type>) ||
(__can_ref_view<_Range>) || (__can_owning_view<_Range>)) constexpr auto
std::ranges::views::_All::operator()(_Range&&) const [with _Range =
std::ranges::concat_view<std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int> >]'
  517 |         ranges::end(__t);
      |         ~~~~~~~~~~~^~~~~
<source>:10:30:   required from here
   10 |     auto c2 = std::views::all(std::views::concat(r2, r1)); // not OK
      |               ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10043:5:  
required by the constraints of 'template<class ... _Vs> template<bool _Const>
constexpr bool std::ranges::operator==(const
concat_view<_Vs>::_Iterator<_Const>&, const
concat_view<_Vs>::_Iterator<_Const>&) requires
(equality_comparable<decltype(std::ranges::__access::__begin((declval<typename
std::__conditional<_Const>::type<const _Vs, _Vs>&>)()))> && ...)'
/opt/compiler-explorer/gcc-trunk-20250702/include/c++/16.0.0/ranges:10044:79:
note: the expression
'(equality_comparable<decltype(std::ranges::__access::__begin((declval<typename
std::__conditional<_Const>::type<const _Vs, _Vs>&>)()))> && ...) [with _Const =
false; _Vs =
{std::ranges::join_view<std::ranges::transform_view<std::ranges::ref_view<std::vector<int,
std::allocator<int> > >, std::ranges::views::_Single> >,
std::ranges::single_view<int>}]' evaluated to 'false'
10044 |       requires (equality_comparable<iterator_t<__maybe_const_t<_Const,
_Vs>>> && ...)
      |               
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
(cropped since the messages repeat from there)

Reply via email to