[libc++] Support immovable return types in std::function.

LWG reflector consensus is that this was a bug in libc++.
(In particular, MSVC also will fix it in their STL, soon.)
Bug originally discovered by Logan Smith.

Also fix `std::function<const void()>`, which should work
the same way as `std::function<void()>` in terms of allowing
"conversions" from non-void types.

Differential Revision: https://reviews.llvm.org/D94452

GitOrigin-RevId: f9b6fd269b6fd2b085c3537b6730a02503430ef0
diff --git a/include/__functional_base b/include/__functional_base
index 708c1a2..1c02e96 100644
--- a/include/__functional_base
+++ b/include/__functional_base
@@ -308,7 +308,7 @@
 #endif  // !defined(_LIBCPP_CXX03_LANG)
 
 
-template <class _Ret>
+template <class _Ret, bool = is_void<_Ret>::value>
 struct __invoke_void_return_wrapper
 {
 #ifndef _LIBCPP_CXX03_LANG
@@ -339,8 +339,8 @@
 #endif
 };
 
-template <>
-struct __invoke_void_return_wrapper<void>
+template <class _Ret>
+struct __invoke_void_return_wrapper<_Ret, true>
 {
 #ifndef _LIBCPP_CXX03_LANG
     template <class ..._Args>
diff --git a/include/functional b/include/functional
index 441a741..67baa5b 100644
--- a/include/functional
+++ b/include/functional
@@ -2348,9 +2348,9 @@
     template <class _Fp>
         struct __callable<_Fp, true>
         {
-            static const bool value = is_same<void, _Rp>::value ||
-                is_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type,
-                               _Rp>::value;
+            static const bool value = is_void<_Rp>::value ||
+                __is_core_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type,
+                                      _Rp>::value;
         };
     template <class _Fp>
         struct __callable<_Fp, false>
diff --git a/include/type_traits b/include/type_traits
index 48884ea..59dfd1e 100644
--- a/include/type_traits
+++ b/include/type_traits
@@ -1665,6 +1665,21 @@
     = is_base_of<_Bp, _Dp>::value;
 #endif
 
+// __is_core_convertible
+
+// [conv.general]/3 says "E is convertible to T" whenever "T t=E;" is well-formed.
+// We can't test for that, but we can test implicit convertibility by passing it
+// to a function. Notice that __is_core_convertible<void,void> is false,
+// and __is_core_convertible<immovable-type,immovable-type> is true in C++17 and later.
+
+template <class _Tp, class _Up, class = void>
+struct __is_core_convertible : public false_type {};
+
+template <class _Tp, class _Up>
+struct __is_core_convertible<_Tp, _Up, decltype(
+    static_cast<void(*)(_Up)>(0) ( static_cast<_Tp(*)()>(0)() )
+)> : public true_type {};
+
 // is_convertible
 
 #if __has_feature(is_convertible_to) && !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK)
diff --git a/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp b/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp
new file mode 100644
index 0000000..ce84cc1
--- /dev/null
+++ b/test/std/utilities/function.objects/func.wrap/func.wrap.func/noncopyable_return_type.pass.cpp
@@ -0,0 +1,138 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <functional>
+
+#include <functional>
+#include <cassert>
+
+#include "test_macros.h"
+
+// Prevent warning on the `const NonCopyable()` function type.
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+
+struct NonCopyable {
+    NonCopyable() = default;
+    NonCopyable(NonCopyable&&) = delete;
+    friend bool operator==(NonCopyable, NonCopyable) { return true; }
+};
+
+struct LargeLambda {
+    int a[100];
+    NonCopyable operator()() const { return NonCopyable(); }
+    NonCopyable operator()(int) const { return NonCopyable(); }
+    NonCopyable f() const { return NonCopyable(); }
+};
+
+void test()
+{
+    std::function<NonCopyable()> f1a = []() { return NonCopyable(); };
+    std::function<NonCopyable()> f2a = +[]() { return NonCopyable(); };
+    std::function<NonCopyable()> f3a = LargeLambda();
+    std::function<NonCopyable()> f4a = std::ref(f1a);
+    std::function<NonCopyable(int)> f1b = [](int) { return NonCopyable(); };
+    std::function<NonCopyable(int)> f2b = +[](int) { return NonCopyable(); };
+    std::function<NonCopyable(int)> f3b = LargeLambda();
+    std::function<NonCopyable(int)> f4b = std::ref(f1b);
+
+    assert(f1a() == f2a());
+    assert(f3a() == f4a());
+    assert(f1b(1) == f2b(1));
+    assert(f3b(1) == f4b(1));
+}
+
+void const_test()
+{
+    std::function<const NonCopyable()> f1a = []() { return NonCopyable(); };
+    std::function<const NonCopyable()> f2a = +[]() { return NonCopyable(); };
+    std::function<const NonCopyable()> f3a = LargeLambda();
+    std::function<const NonCopyable()> f4a = std::ref(f1a);
+    std::function<const NonCopyable(int)> f1b = [](int) { return NonCopyable(); };
+    std::function<const NonCopyable(int)> f2b = +[](int) { return NonCopyable(); };
+    std::function<const NonCopyable(int)> f3b = LargeLambda();
+    std::function<const NonCopyable(int)> f4b = std::ref(f1b);
+
+    assert(f1a() == f2a());
+    assert(f3a() == f4a());
+    assert(f1b(1) == f2b(1));
+    assert(f3b(1) == f4b(1));
+}
+
+void void_test()
+{
+    std::function<void()> f1a = []() { return NonCopyable(); };
+    std::function<void()> f2a = +[]() { return NonCopyable(); };
+    std::function<void()> f3a = LargeLambda();
+    std::function<void()> f4a = std::ref(f1a);
+    std::function<void(int)> f1b = [](int) { return NonCopyable(); };
+    std::function<void(int)> f2b = +[](int) { return NonCopyable(); };
+    std::function<void(int)> f3b = LargeLambda();
+    std::function<void(int)> f4b = std::ref(f1b);
+}
+
+void const_void_test()
+{
+    std::function<const void()> f1a = []() { return NonCopyable(); };
+    std::function<const void()> f2a = +[]() { return NonCopyable(); };
+    std::function<const void()> f3a = LargeLambda();
+    std::function<const void()> f4a = std::ref(f1a);
+    std::function<const void(int)> f1b = [](int) { return NonCopyable(); };
+    std::function<const void(int)> f2b = +[](int) { return NonCopyable(); };
+    std::function<const void(int)> f3b = LargeLambda();
+    std::function<const void(int)> f4b = std::ref(f1b);
+}
+
+void member_pointer_test()
+{
+    std::function<NonCopyable(LargeLambda*)> f1a = &LargeLambda::f;
+    std::function<NonCopyable(LargeLambda&)> f2a = &LargeLambda::f;
+    LargeLambda ll;
+    assert(f1a(&ll) == f2a(ll));
+
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)(), std::function<NonCopyable(LargeLambda*)>>);
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)(), std::function<NonCopyable(LargeLambda&)>>);
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)() const, std::function<NonCopyable(LargeLambda*)>>);
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)() const, std::function<NonCopyable(LargeLambda&)>>);
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)() const, std::function<NonCopyable(const LargeLambda*)>>);
+    static_assert(std::is_convertible_v<NonCopyable (LargeLambda::*)() const, std::function<NonCopyable(const LargeLambda&)>>);
+
+    // Verify we have SFINAE against invoking a pointer-to-data-member in a way that would have to copy the NonCopyable.
+    static_assert(!std::is_convertible_v<NonCopyable LargeLambda::*, std::function<NonCopyable(LargeLambda*)>>);
+    static_assert(!std::is_convertible_v<NonCopyable LargeLambda::*, std::function<NonCopyable(LargeLambda&)>>);
+    static_assert(!std::is_convertible_v<NonCopyable LargeLambda::*, std::function<NonCopyable&(const LargeLambda&)>>);
+    static_assert(std::is_convertible_v<NonCopyable LargeLambda::*, std::function<NonCopyable&(LargeLambda*)>>);
+    static_assert(std::is_convertible_v<NonCopyable LargeLambda::*, std::function<NonCopyable&(LargeLambda&)>>);
+    static_assert(std::is_convertible_v<NonCopyable LargeLambda::*, std::function<const NonCopyable&(const LargeLambda&)>>);
+}
+
+void ctad_test()
+{
+    std::function f1a = []() { return NonCopyable(); };
+    std::function f2a = +[]() { return NonCopyable(); };
+    std::function f1b = [](int) { return NonCopyable(); };
+    std::function f2b = +[](int) { return NonCopyable(); };
+    static_assert(std::is_same_v<decltype(f1a), std::function<NonCopyable()>>);
+    static_assert(std::is_same_v<decltype(f2a), std::function<NonCopyable()>>);
+    static_assert(std::is_same_v<decltype(f1b), std::function<NonCopyable(int)>>);
+    static_assert(std::is_same_v<decltype(f2b), std::function<NonCopyable(int)>>);
+}
+
+int main(int, char**)
+{
+    test();
+    const_test();
+    void_test();
+    const_void_test();
+    member_pointer_test();
+    ctad_test();
+    return 0;
+}