Project

General

Profile

Actions

Bug #54303

closed

c++20: beast compilation failures in HttpSession::connect()

Added by Casey Bodley about 2 years ago. Updated about 2 years ago.

Status:
Resolved
Priority:
Normal
Assignee:
Target version:
-
% Done:

0%

Source:
Tags:
Backport:
Regression:
No
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Pull request ID:
Crash signature (v1):
Crash signature (v2):

Description

with c++20 enabled, src/librbd/migration/HttpClient.cc fails to compile because it appears to choose the wrong overload of boost::beast::tcp_stream::async_connect():

/usr/bin/c++ -DBOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION -DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT -DHAVE_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_REENTRANT -D_THREAD_SAFE -D__CEPH__ -D__STDC_FORMAT_MACROS -D__linux__ -Iceph/build/src/include -Iceph/src -isystem ceph/build/include -isystem ceph/src/xxHash -isystem ceph/src/rapidjson/include -isystem ceph/src/fmt/include -g -Og -fPIC -Wall -fno-strict-aliasing -fsigned-char -Wtype-limits -Wignored-qualifiers -Wpointer-arith -Werror=format-security -Winit-self -Wno-unknown-pragmas -Wnon-virtual-dtor -Wno-ignored-qualifiers -ftemplate-depth-1024 -Wpessimizing-move -Wredundant-move -Wstrict-null-sentinel -Woverloaded-virtual -fno-new-ttp-matching -DCEPH_DEBUG_MUTEX -fstack-protector-strong -D_GLIBCXX_ASSERTIONS -fdiagnostics-color=auto -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -f
no-builtin-free -std=c++20 -MD -MT src/librbd/CMakeFiles/rbd_internal.dir/migration/HttpClient.cc.o -MF src/librbd/CMakeFiles/rbd_internal.dir/migration/HttpClient.cc.o.d -o src/librbd/CMakeFiles/rbd_internal.dir/migration/HttpClient.cc.o -c ceph/src/librbd/migration/HttpClient.cc
In file included from ceph/src/librbd/migration/HttpClient.cc:10:
ceph/src/librbd/asio/Utils.h: In instantiation of ‘librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)> [with auto:62 = {}]’:
/usr/include/boost/asio/async_result.hpp:46:4:   required from ‘struct boost::asio::detail::is_completion_handler_for<librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)>, void(boost::system::error_code)>’
/usr/include/boost/asio/async_result.hpp:72:57:   required by substitution of ‘template<class Initiation, class RawCompletionToken, class ... Args>  requires  completion_handler_for<RawCompletionToken, Signature> static boost::asio::async_result<librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)>, void(boost::system::error_code)>::return_type boost::asio::async_result<librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)>, void(boost::system::error_code)>::initiate<Initiation, RawCompletionToken, Args ...>(Initiation&&, RawCompletionToken&&, Args&& ...) [with Initiation = librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)>; RawCompletionToken = void(boost::system::error_code); Args = <missing>]’
/usr/include/boost/asio/async_result.hpp:355:5:   required by substitution of ‘template<class CompletionToken, class Signature, class Initiation, class ... Args>  requires  completion_signature<Signature> typename boost::asio::constraint<boost::asio::detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value, decltype (boost::asio::async_result<typename std::decay<_Tp>::type, Signature>::initiate(declval<Initiation&&>(), declval<CompletionToken&&>(), (declval<Args&&>)()...))>::type boost::asio::async_initiate(Initiation&&, CompletionToken&, Args&& ...) [with CompletionToken = librbd::asio::util::get_callback_adapter<librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)> >(librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>&&)::<lambda(boost::system::error_code, auto:62&& ...)>; Signature = void(boost::system::error_code); Initiation = boost::asio::detail::initiation_archetype<void(boost::system::error_code)>; Args = {}]’
/usr/include/boost/asio/async_result.hpp:498:33:   required by substitution of ‘template<class ConnectHandler>  requires  completion_token_for<ConnectHandler, void()> auto boost::beast::basic_stream<boost::asio::ip::tcp, boost::asio::executor, boost::beast::unlimited_rate_policy>::async_connect<ConnectHandler>(const endpoint_type&, ConnectHandler&&) [with ConnectHandler = boost::asio::ip::tcp]’
ceph/src/librbd/migration/HttpClient.cc:604:27:   required from ‘void librbd::migration::HttpClient<ImageCtxT>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*) [with I = librbd::ImageCtx; boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type = boost::asio::ip::basic_resolver_results<boost::asio::ip::tcp>]’
ceph/src/librbd/migration/HttpClient.cc:946:35:   required from here
ceph/src/librbd/asio/Utils.h:25:8: error: no match for call to ‘(const librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>) (int)’
   25 |       t(-ec.value(), std::forward<decltype(args)>(args)...);
      |       ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ceph/src/librbd/migration/HttpClient.cc:607:9: note: candidate: ‘template<class auto:114> librbd::migration::HttpClient<librbd::ImageCtx>::PlainHttpSession::connect(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::results_type, Context*)::<lambda(int, auto:114)>’
  607 |         [on_finish](int r, auto endpoint) { on_finish->complete(r); }));
      |         ^
ceph/src/librbd/migration/HttpClient.cc:607:9: note:   template argument deduction/substitution failed:
In file included from ceph/src/librbd/migration/HttpClient.cc:10:
ceph/src/librbd/asio/Utils.h:25:8: note:   candidate expects 2 arguments, 1 provided
   25 |       t(-ec.value(), std::forward<decltype(args)>(args)...);
      |       ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

the async_connect() overloads are documented in https://www.boost.org/doc/libs/1_78_0/libs/beast/doc/html/beast/ref/boost__beast__basic_stream/async_connect.html

both PlainHttpSession::connect() and SslHttpSession::connect() pass boost::asio::ip::tcp::resolver::results_type as the first argument, so clearly intend to call the async_connect(const EndpointSequence&, RangeConnectHandler&&) overload

however, the compilation fails inside the async_connect(const endpoint_type&, ConnectHandler&&) overload which can't match the first argument at all

i believe the underlying issue is related to beast's use of c++20 concepts to constrain these overloads, along with librbd::asio::util::get_callback_adapter()'s use of a variadic lambda to wrap the completion handler for connect

the async_connect() overloads use the completion_token_for<T> concept from boost::asio to check that the completion handler is callable with the expected signature. however, the variadic lambda returned by get_callback_adapter() satisfies the constraints of both completion_token_for<ConnectHandler> and completion_token_for<RangeConnectHandler>

i'm still not clear on exactly how concepts interact with overload resultion to produce this error

Actions #1

Updated by Casey Bodley about 2 years ago

  • Assignee set to Casey Bodley
  • Pull request ID set to 45062
Actions #2

Updated by Ilya Dryomov about 2 years ago

  • Status changed from New to Fix Under Review
Actions #3

Updated by Ilya Dryomov about 2 years ago

  • Status changed from Fix Under Review to Resolved
Actions

Also available in: Atom PDF