@@ -2346,15 +2346,6 @@ constexpr bool args_are_all_positional() {
23462346 return all_of<is_positional<Args>...>::value;
23472347}
23482348
2349- // [workaround(intel)] Separate function required here
2350- // We need to put this into a separate function because the Intel compiler
2351- // fails to compile enable_if_t<!all_of<is_positional<Args>...>::value>
2352- // (tested with ICC 2021.1 Beta 20200827).
2353- template <typename ... Args>
2354- constexpr bool args_have_kw () {
2355- return none_of<is_keyword_or_ds<Args>...>::value;
2356- }
2357-
23582349#if PY_VERSION_HEX < 0x030C0000
23592350// / Collect only positional arguments for a Python function call
23602351template <return_value_policy policy,
@@ -2385,24 +2376,20 @@ class unpacking_vectorcall_collector {
23852376public:
23862377 template <typename ... Ts>
23872378 explicit unpacking_vectorcall_collector (Ts &&...values) {
2388-
23892379 m_args.reserve (sizeof ...(values) + 1 );
23902380 m_args.push_back (
23912381 nullptr ); // dummy first argument so we can use PY_VECTORCALL_ARGUMENTS_OFFSET
23922382
2383+ object names_list; // null or a list of names
2384+
23932385 // collect_arguments guarantees this can't be constructed with kwargs before the last
23942386 // positional so we don't need to worry about Ts... being in anything but normal python
23952387 // order.
23962388 using expander = int [];
2397- if (args_have_kw<Ts...>()) {
2398- (void ) expander{0 , (positional (std::forward<Ts>(values)), 0 )...};
2399- } else {
2400- list names_list;
2401-
2402- (void ) expander{0 , (process (names_list, std::forward<Ts>(values)), 0 )...};
2389+ (void ) expander{0 , (process (names_list, std::forward<Ts>(values)), 0 )...};
24032390
2404- if (! names_list. empty ())
2405- m_names = reinterpret_steal<tuple>(PyList_AsTuple (names_list.ptr ()));
2391+ if (names_list) {
2392+ m_names = reinterpret_steal<tuple>(PyList_AsTuple (names_list.ptr ()));
24062393 }
24072394 }
24082395
@@ -2438,7 +2425,7 @@ class unpacking_vectorcall_collector {
24382425 dict kwargs () const {
24392426 dict val;
24402427 if (m_names) {
2441- tuple namestup (m_names);
2428+ auto namestup = reinterpret_borrow<tuple> (m_names);
24422429 size_t offset = m_args.size () - namestup.size ();
24432430 for (size_t i = 0 ; i < namestup.size (); ++i, ++offset) {
24442431 val[namestup[i]] = reinterpret_borrow<object>(m_args[offset]);
@@ -2450,7 +2437,7 @@ class unpacking_vectorcall_collector {
24502437private:
24512438 // normal argument, possibly needing conversion
24522439 template <typename T>
2453- void positional ( T &&x) {
2440+ void process (object & /* names_list */ , T &&x) {
24542441 auto o = reinterpret_steal<object>(
24552442 detail::make_caster<T>::cast (std::forward<T>(x), policy, {}));
24562443 if (!o) {
@@ -2465,7 +2452,8 @@ class unpacking_vectorcall_collector {
24652452 m_temp.push_back (std::move (o));
24662453 }
24672454
2468- void positional (detail::args_proxy ap) {
2455+ // * unpacking
2456+ void process (object & /* names_list*/ , detail::args_proxy ap) {
24692457 if (!ap) {
24702458 return ;
24712459 }
@@ -2475,17 +2463,11 @@ class unpacking_vectorcall_collector {
24752463 }
24762464 }
24772465
2478- // normal argument, possibly needing conversion
2479- template <typename T>
2480- void process (list & /* names_list*/ , T &&x) {
2481- positional (std::forward<T>(x));
2482- }
2483-
2484- // * unpacking
2485- void process (list & /* names_list*/ , detail::args_proxy ap) { positional (ap); }
2486-
24872466 // named argument
2488- void process (list &names_list, arg_v a) {
2467+ void process (object &names_list, arg_v a) {
2468+ if (!names_list) {
2469+ names_list = list ();
2470+ }
24892471 if (!a.name ) {
24902472# if !defined(PYBIND11_DETAILED_ERROR_MESSAGES)
24912473 nameless_argument_error ();
@@ -2508,16 +2490,22 @@ class unpacking_vectorcall_collector {
25082490 throw cast_error_unable_to_convert_call_arg (a.name , a.type );
25092491# endif
25102492 }
2511- names_list.append (std::move (name));
2493+ if (PyList_Append (names_list.ptr (), name.release ().ptr ()) < 0 )
2494+ {
2495+ throw error_already_set ();
2496+ }
25122497 m_temp.push_back (a.value ); // keep alive
25132498 m_args.push_back (a.value .ptr ());
25142499 }
25152500
25162501 // ** unpacking
2517- void process (list &names_list, detail::kwargs_proxy kp) {
2502+ void process (object &names_list, detail::kwargs_proxy kp) {
25182503 if (!kp) {
25192504 return ;
25202505 }
2506+ if (!names_list) {
2507+ names_list = list ();
2508+ }
25212509 for (auto &&k : reinterpret_borrow<dict>(kp)) {
25222510 auto name = str (k.first );
25232511 if (names_list.contains (name)) {
@@ -2527,7 +2515,10 @@ class unpacking_vectorcall_collector {
25272515 multiple_values_error (name);
25282516# endif
25292517 }
2530- names_list.append (std::move (name));
2518+ if (PyList_Append (names_list.ptr (), name.release ().ptr ()) < 0 )
2519+ {
2520+ throw error_already_set ();
2521+ }
25312522 m_temp.push_back (reinterpret_borrow<object>(k.second )); // keep alive
25322523 m_args.push_back (k.second .ptr ());
25332524 }
@@ -2556,7 +2547,7 @@ class unpacking_vectorcall_collector {
25562547
25572548private:
25582549 small_vector<PyObject *, arg_vector_small_size> m_args;
2559- object m_names; // todo: use m_temp for this?
2550+ object m_names; // null or a tuple of names
25602551 small_vector<object, arg_vector_small_size> m_temp;
25612552};
25622553
0 commit comments