https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109680
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- template <typename T, typename U = T&&> U __declval (int); template <typename T> T __declval (long); template <typename T> auto declval () noexcept -> decltype (__declval <T> (0)); using To = int () const; using From = int (*) (); To foo () { return declval <From> (); } >From bar () { return declval <To> (); } static_assert (!__is_convertible (To, From), ""); static_assert (!__is_convertible (From, To), ""); should show that both assertions should succeed. Dunno if in this case the reason why it isn't convertible is simply the fact that functions can't be declared to return function/method/array types or some other reason as well.