public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/103663] New: Diagnostic is missing multiple instantiation frames to help point to where the problem happens
@ 2021-12-11 19:56 barry.revzin at gmail dot com
  2023-04-03  2:39 ` [Bug c++/103663] " pinskia at gcc dot gnu.org
  0 siblings, 1 reply; 2+ messages in thread
From: barry.revzin at gmail dot com @ 2021-12-11 19:56 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 103663
           Summary: Diagnostic is missing multiple instantiation frames to
                    help point to where the problem happens
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

I'm sorry for how not-remotely-reduced these examples are, but I'm not sure how
to do better.

=======================================================

Consider this bug in range-v3 that we're trying to figure out how to solve
(this is a range-v3 library issue, not a gcc or libstdc++ issue):

#include <range/v3/view/zip.hpp>

struct Abstract {
    virtual auto f() -> int = 0;
};

struct V {
    auto begin() -> Abstract*;
    auto end() -> Abstract*;
};

void use(V v) {
    auto z = ranges::views::zip(v);
    z.begin();
}

This code doesn't compile. With gcc 11.2 -std=c++20
(https://godbolt.org/z/h4d14jeMa), the diagnostics I get on compiler explorer
are:

In file included from
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/zip.hpp:17,
                 from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/tuple: In instantiation of
'struct std::_Head_base<0, Abstract, false>':
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/tuple:407:12:   required
from 'struct std::_Tuple_impl<0, Abstract>'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/tuple:599:11:   required
from 'class std::tuple<Abstract>'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/functional/invoke.hpp:138:40:
  required from 'constexpr decltype
((F&&)(f)((Args&&(ranges::invoke_fn::operator()::args))...))
ranges::invoke_fn::operator()(F&&, Args&& ...) const [with F =
ranges::detail::indirect_zip_fn_&; Args = {ranges::copy_tag, Abstract*};
decltype ((F&&)(f)((Args&&(ranges::invoke_fn::operator()::args))...)) =
std::tuple<Abstract>]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/functional/concepts.hpp:36:5:
  required by substitution of 'template<bool Const>  requires  Const &&
(and_v<range<const Rngs>...>) && (zippable_with<Fun, typename
meta::detail::_if_<std::integral_constant<bool, Const>, const Rngs>::type ...>)
ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >::cursor<Const>
ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >::begin_cursor<Const>() const [with bool Const =
ranges::detail::indirect_zip_fn_]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/detail/range_access.hpp:85:31:
  required by substitution of 'template<class Rng> static constexpr decltype
(rng.begin_cursor()) ranges::range_access::begin_cursor(Rng&) [with Rng = const
ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/facade.hpp:39:39:
  required by substitution of 'template<class Derived> using facade_iterator_t
= ranges::basic_iterator<typename std::decay<decltype
(ranges::range_access::begin_cursor(declval<Derived&>()))>::type> [with Derived
= const ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/facade.hpp:106:24:
  required by substitution of 'template<class D>  requires  same_as<D, Derived>
constexpr ranges::detail::facade_iterator_t<const D>
ranges::view_facade<ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >, ranges::finite>::begin<D>() const [with D =
ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >]'
<source>:14:12:   required from here
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/tuple:224:13: error:
cannot declare field 'std::_Head_base<0, Abstract, false>::_M_head_impl' to be
of abstract type 'Abstract'
  224 |       _Head _M_head_impl;
      |             ^~~~~~~~~~~~
<source>:3:8: note:   because the following virtual functions are pure within
'Abstract':
    3 | struct Abstract {
      |        ^~~~~~~~
<source>:4:18: note:     'virtual int Abstract::f()'
    4 |     virtual auto f() -> int = 0;
      |                  ^

The instantiation stack points to tuple, invoke.hpp, concepts.hpp,
range_access.hpp, facade.hpp. But the problem comes from zip_with.hpp. This is
not really possible to track down from the diagnostic.

To help illustrate what I mean, this line:

/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/detail/range_access.hpp:85:31:
  required by substitution of 'template<class Rng> static constexpr decltype
(rng.begin_cursor()) ranges::range_access::begin_cursor(Rng&) [with Rng = const
ranges::iter_zip_with_view<ranges::detail::indirect_zip_fn_,
ranges::ref_view<V> >]'

points us to here:

        template<typename Rng>
        static constexpr auto CPP_auto_fun(begin_cursor)(Rng &rng)
        (
            return rng.begin_cursor()
        )

Which is a macro that expands to:

        template<typename Rng>
        static constexpr auto begin_cursor (Rng &rng)
noexcept(noexcept(rng.begin_cursor())) -> decltype(rng.begin_cursor()) { return
(rng.begin_cursor()); }

The next instantiation stack frame points us to here:

    template<typename Fun, typename... Args>
    CPP_requires(invocable_,
        requires(Fun && fn) //
        (
            invoke((Fun &&) fn, std::declval<Args>()...)
        ));


Which is a macro that expands to:

template<typename Fun, typename... Args>
concept invocable__requires_ = requires(Fun && fn) { invoke((Fun &&) fn,
std::declval<Args>()...); }



      ;
template<typename Fun, typename... Args>
concept invocable =
    ranges::invocable__requires_<Fun, Args...>;


But... how did we get from the begin_cursor call (which doesn't use concepts
anywhere) to this concept? The clue is kind of in the text afterwards. We try
to call this particular begin_cursor() (this is zip_with.hpp:329-336):

        template(bool Const = true)(
            /// \pre
            requires Const AND and_v<range<Rngs const>...> AND
                views::zippable_with<Fun, meta::if_c<Const, Rngs const>...>)
        cursor<Const> begin_cursor() const
        {
            return {fun_, tuple_transform(rngs_, ranges::begin)};
        }

And in that zip_with, we check zippable_with preprocesses out into:

        template<typename Fun, typename... Rngs > concept
zippable_with__concept_ = invocable<Fun&, iterator_t<Rngs>...> &&
invocable<Fun&, copy_tag, iterator_t<Rngs>...> && invocable<Fun&, move_tag,
iterator_t<Rngs>...>




         ;
        template<typename Fun, typename ...Rngs>
        concept zippable_with =
            and_v<input_range<Rngs>...> &&
            copy_constructible<Fun> &&
            views::zippable_with__concept_<Fun, Rngs...>;

And there now is the invocable check.

But this would've been a lot easier to track down if these two zip_with.hpp
frames were present. 

==============================

A similar, shorter example of disappearing frames:

#include <range/v3/view/zip.hpp>

struct Abstract {
    virtual void f() = 0;
};

using T = ranges::common_reference_t<ranges::common_tuple<Abstract&>,
std::tuple<Abstract>&>;

which gives me (https://godbolt.org/z/MdvrYGxYr):

/opt/compiler-explorer/gcc-trunk-20211211/include/c++/12.0.0/tuple:416:12:  
required from 'struct std::_Tuple_impl<0, Abstract>'
/opt/compiler-explorer/gcc-trunk-20211211/include/c++/12.0.0/tuple:609:11:  
required from 'class std::tuple<Abstract>'
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:92:41:
  required by substitution of 'template<class T, class U> struct
concepts::detail::_builtin_common_2<T, U, meta::void_<decltype ((true ? 
declval<T>() : declval<U>()))> > [with T = ranges::common_tuple<Abstract&>; U =
std::tuple<Abstract>&]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:365:12:
  recursively required by substitution of 'template<class T, class U> struct
concepts::detail::_common_reference2<T, U, typename
concepts::detail::if_<std::is_reference<typename
concepts::detail::_builtin_common<T, U>::type>::value>::invoke<void> > [with T
= ranges::common_tuple<Abstract&>; U = std::tuple<Abstract>&]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:365:12:
  required from 'struct
concepts::common_reference<ranges::common_tuple<Abstract&>,
std::tuple<Abstract>&>'
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:370:11:
  required by substitution of 'template<class ... Ts> using common_reference_t
= typename concepts::common_reference::type [with Ts =
{ranges::common_tuple<Abstract&>, std::tuple<Abstract>&}]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/common_type.hpp:47:11:
  required by substitution of 'template<class ... Ts> using common_reference_t
= concepts::common_reference_t<Ts ...> [with Ts =
{ranges::common_tuple<Abstract&>, std::tuple<Abstract>&}]'
<source>:7:92:   required from here

But there are a lot of steps from type_traits.hpp:365 to type_traits.hpp:92.
Clang hides them by default, but let's me expose them
(https://godbolt.org/z/b6dne6c85):

/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:92:41:
note: in instantiation of template class 'std::tuple<Abstract>' requested here
        using _cond_res = decltype(true ? std::declval<T>() :
std::declval<U>());
                                        ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:146:52:
note: in instantiation of template type alias '_cond_res' requested here
        struct _builtin_common_2<T, U, meta::void_<_cond_res<T, U>>>
                                                   ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:151:15:
note: during template argument deduction for class template partial
specialization '_builtin_common_2<T, U>' [with T =
ranges::common_tuple<Abstract &>, U = std::tuple<Abstract> &]
            : _builtin_common_2<T, U>
              ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:151:15:
note: in instantiation of template class
'concepts::detail::_builtin_common_2<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>' requested here
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta_fwd.hpp:298:18:
note: in instantiation of template class
'concepts::detail::_builtin_common<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>' requested here
        typename T::type;
                 ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta_fwd.hpp:298:9:
note: in instantiation of requirement here
        typename T::type;
        ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta_fwd.hpp:296:26:
note: while substituting template arguments into constraint expression here
    META_CONCEPT trait = requires
                         ^~~~~~~~
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta.hpp:140:36: note:
while checking the satisfaction of concept
'trait<concepts::detail::_builtin_common<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>>' requested here
    template <META_TYPE_CONSTRAINT(trait) T>
                                   ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta.hpp:140:36: note:
while substituting template arguments into constraint expression here
    template <META_TYPE_CONSTRAINT(trait) T>
                                   ^~~~~
/opt/compiler-explorer/libs/rangesv3/trunk/include/meta/meta_fwd.hpp:155:35:
note: expanded from macro 'META_TYPE_CONSTRAINT'
#define META_TYPE_CONSTRAINT(...) __VA_ARGS__
                                  ^~~~~~~~~~~
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:89:9:
note: while checking constraint satisfaction for template
'_t<concepts::detail::_builtin_common<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>>' required here
        using _builtin_common_t = meta::_t<_builtin_common<T, U>>;
        ^~~~~
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:346:64:
note: in instantiation of template type alias '_builtin_common_t' requested
here
        struct _common_reference2<T, U,
if_t<std::is_reference<_builtin_common_t<T, U>>::value>>
                                                               ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:366:11:
note: during template argument deduction for class template partial
specialization '_common_reference2<T, U,
if_t<std::is_reference<_builtin_common_t<T, U>>::value>>' [with T =
ranges::common_tuple<Abstract &>, U = std::tuple<Abstract> &]
        : detail::_common_reference2<T, U>
          ^
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:366:11:
note: in instantiation of template class
'concepts::detail::_common_reference2<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>' requested here
/opt/compiler-explorer/libs/rangesv3/trunk/include/concepts/type_traits.hpp:370:5:
note: in instantiation of template class
'concepts::common_reference<ranges::common_tuple<Abstract &>,
std::tuple<Abstract> &>' requested here
    using common_reference_t = typename common_reference<Ts...>::type;
    ^

Which is also a lot more helpful.

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [Bug c++/103663] Diagnostic is missing multiple instantiation frames to help point to where the problem happens
  2021-12-11 19:56 [Bug c++/103663] New: Diagnostic is missing multiple instantiation frames to help point to where the problem happens barry.revzin at gmail dot com
@ 2023-04-03  2:39 ` pinskia at gcc dot gnu.org
  0 siblings, 0 replies; 2+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-04-03  2:39 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=90508

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Maybe similar to PR 90508.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-04-03  2:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-11 19:56 [Bug c++/103663] New: Diagnostic is missing multiple instantiation frames to help point to where the problem happens barry.revzin at gmail dot com
2023-04-03  2:39 ` [Bug c++/103663] " pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).