ThePhD / sol2

Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:
http://sol2.rtfd.io/
MIT License
4.22k stars 517 forks source link

Definition SOL_SAFE_USERTYPE is 0, sol compilation fails #1576

Open wzhengsen opened 9 months ago

wzhengsen commented 9 months ago

sol version: develop branch compiler: msvc c++: c++20 code:

#define SOL_SAFE_USERTYPE 0
//#define SOL_SAFE_USERTYPE 1 // When defined as 1, compilation passes
#include <sol.hpp>
#include <span>

template <class _Ty, size_t _Extent = std::dynamic_extent>
[[nodiscard]] std::span<_Ty, _Extent> sol_lua_get(
     sol::types<std::span<_Ty, _Extent>>, ::lua_State* L,
     int idx, sol::stack::record& tracking) {
    return std::span<_Ty, _Extent>();
}

int main() {
    std::span<const std::string> sp = {};
    sol::function f = {};
    f(sp);// compile error
    return 0;
}
wzhengsen commented 9 months ago

Just now, found out that compiling with clang also has this error.

Rochet2 commented 9 months ago

This is the error (godbolt)

In file included from <source>:4:
In file included from /opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/sol.hpp:54:
In file included from /opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype.hpp:27:
In file included from /opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_core.hpp:37:
In file included from /opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container_launch.hpp:28:
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container.hpp:541:12: error: non-const lvalue reference to type 'span<...>' cannot bind to a temporary of type 'span<...>'
  541 |                                 return stack::unqualified_get<T>(L, 1);
      |                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container.hpp:1212:17: note: in instantiation of member function 'sol::container_detail::usertype_container_default<std::span<std::basic_string<char>>>::get_src' requested here
 1212 |                                 auto& src = get_src(L);
      |                                             ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container.hpp:1353:12: note: in instantiation of function template specialization 'sol::container_detail::usertype_container_default<std::span<std::basic_string<char>>>::pairs_associative<false>' requested here
 1353 |                                 return pairs_associative<false>(is_assoc(), L);
      |                                        ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container_launch.hpp:125:16: note: in instantiation of member function 'sol::container_detail::usertype_container_default<std::span<std::basic_string<char>>>::pairs' requested here
  125 |                                 return uc::pairs(L);
      |                                            ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container_launch.hpp:133:12: note: in instantiation of member function 'sol::container_detail::u_c_launch<std::span<std::basic_string<char>>>::real_pairs_traits' requested here
  133 |                                 return real_pairs_traits(container_detail::has_traits_pairs<uc>(), L);
      |                                        ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container_launch.hpp:286:74: note: in instantiation of member function 'sol::container_detail::u_c_launch<std::span<std::basic_string<char>>>::real_pairs_call' requested here
  286 |                                 return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
      |                                                                                                      ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/usertype_container_launch.hpp:335:46: note: (skipping 8 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
  335 |                                                 { "__pairs", &meta_usertype_container::pairs_call },
      |                                                                                        ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/stack_core.hpp:948:19: note: in instantiation of function template specialization 'sol::stack::push<sol::detail::as_reference_tag, std::span<std::basic_string<char>> &, void>' requested here
  948 |                                 return stack::push<Tr>(L, std::forward<Arg>(arg), std::forward<Args>(args)...);
      |                                               ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/stack_core.hpp:955:25: note: in instantiation of function template specialization 'sol::stack::stack_detail::push_reference<std::span<std::basic_string<char>> &, std::span<std::basic_string<char>> &>' requested here
  955 |                         return stack_detail::push_reference<T>(L, std::forward<T>(t), std::forward<Args>(args)...);
      |                                              ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/stack_core.hpp:982:20: note: in instantiation of function template specialization 'sol::stack::push_reference<std::span<std::basic_string<char>> &>' requested here
  982 |                         int pushcount = push_reference(L, std::forward<T>(t));
      |                                         ^
/opt/compiler-explorer/libs/sol2/v3.2.1/include/sol/unsafe_function.hpp:169:27: note: in instantiation of function template specialization 'sol::stack::multi_push_reference<std::span<std::basic_string<char>> &>' requested here
  169 |                         int pushcount = stack::multi_push_reference(lua_state(), std::forward<Args>(args)...);
      |                                                ^
<source>:21:4: note: in instantiation of function template specialization 'sol::basic_function<sol::basic_reference<false>, false>::operator()<std::span<std::basic_string<char>> &>' requested here
   21 |         f1(sp);// compile error
      |           ^
3 warnings and 1 error generated.

Looks like the issue is here https://github.com/ThePhD/sol2/blob/e8e122e9ce46f4f1c0b04003d8b703fe1b89755a/include/sol/usertype_container.hpp#L557

The function returns auto&, but when #define SOL_SAFE_USERTYPE 0 is set, stack::unqualified_get<T>(L_, 1); is returned. Changing it to stack::unqualified_get<T&>(L_, 1); probably fixes the issue, as it is similar to the code when the setting is on.

wzhengsen commented 9 months ago

@Rochet2 You inspired me to try your program. But it still doesn't pass compilation and I used instead:

return *stack::unqualified_get<T*>(L_, 1);

It works.