Skip to content

Commit 25485b3

Browse files
committed
Fix args expansion
This would be easier with `if constexpr`
1 parent cc2b5a9 commit 25485b3

1 file changed

Lines changed: 26 additions & 35 deletions

File tree

include/pybind11/cast.h

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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
23602351
template <return_value_policy policy,
@@ -2385,24 +2376,20 @@ class unpacking_vectorcall_collector {
23852376
public:
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 {
24502437
private:
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

25572548
private:
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

Comments
 (0)