From 058a02ab4b98a0e55a806cb3c80f315d713ebab0 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 8 Oct 2025 16:54:48 -0700 Subject: [PATCH 1/9] Centralize readable function signatures to avoid duplication This seems to reduce size costs of adding enum_-specific implementations of dunder methods, but also should provide a nice to have size optimization for programs that use pybind11 in general. --- include/pybind11/pybind11.h | 52 ++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 515aab1414..37b3df573c 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -248,6 +248,47 @@ inline std::string generate_type_signature() { # define PYBIND11_COMPAT_STRDUP strdup #endif +#define PYBIND11_READABLE_SIGNATURE_EXPR \ + detail::const_name("(") + cast_in::arg_names + detail::const_name(") -> ") + cast_out::name + +// We centralize readable function signatures in a specific template +// so that we don't duplicate them across different instantiations of +// cpp_function::initialize (which is templated on more types). +template +class ReadableFunctionSignature { +private: + // We have to repeat PYBIND11_READABLE_SIGNATURE_EXPR in decltype() + // because C++11 doesn't allow functions to return `auto`. (We don't + // know the type because it's some variant of detail::descr with + // unknown N.) + static constexpr decltype(PYBIND11_READABLE_SIGNATURE_EXPR) readable_signature() { + return PYBIND11_READABLE_SIGNATURE_EXPR; + } + +public: + static constexpr decltype(readable_signature()) kReadableSignature = readable_signature(); +#if !defined(_MSC_VER) + static constexpr decltype(decltype(kReadableSignature)::types()) kTypes + = decltype(kReadableSignature)::types(); +#endif +}; +#undef PYBIND11_READABLE_SIGNATURE_EXPR + +// Prior to C++17, we don't have inline variables, so we have to provide an out-of-line definition +// of the class member. +PYBIND11_WARNING_PUSH +PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") +template +constexpr decltype(ReadableFunctionSignature::readable_signature()) + ReadableFunctionSignature::kReadableSignature; +#if !defined(_MSC_VER) +template +constexpr decltype(decltype(ReadableFunctionSignature::kReadableSignature)::types()) + ReadableFunctionSignature::kTypes; +#endif +PYBIND11_WARNING_POP + PYBIND11_NAMESPACE_END(detail) /// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object @@ -481,9 +522,14 @@ class cpp_function : public function { /* Generate a readable signature describing the function's arguments and return value types */ - static constexpr auto signature - = const_name("(") + cast_in::arg_names + const_name(") -> ") + cast_out::name; - PYBIND11_DESCR_CONSTEXPR auto types = decltype(signature)::types(); + static constexpr const auto &signature + = detail::ReadableFunctionSignature::kReadableSignature; +#if !defined(_MSC_VER) + static constexpr const auto &types + = detail::ReadableFunctionSignature::kTypes; +#else + PYBIND11_DESCR_CONSTEXPR auto types = std::decay::type::types(); +#endif /* Register the function with Python from generic (non-templated) code */ // Pass on the ownership over the `unique_rec` to `initialize_generic`. `rec` stays valid. From 3fa3d553a61fb4502b19e2ebad5213cb6253e25e Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 8 Oct 2025 20:43:53 -0700 Subject: [PATCH 2/9] gate disabling of -Wdeprecated-redundant-constexpr-static-def to clang 17+ --- include/pybind11/pybind11.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 37b3df573c..957d0d36c8 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -277,7 +277,9 @@ class ReadableFunctionSignature { // Prior to C++17, we don't have inline variables, so we have to provide an out-of-line definition // of the class member. PYBIND11_WARNING_PUSH +#if defined(__clang_major__) && __clang_major__ >= 17 PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") +#endif template constexpr decltype(ReadableFunctionSignature::readable_signature()) ReadableFunctionSignature::kReadableSignature; From cd1f09c696d917205f30397ae60c39b5ec4ae87e Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 8 Oct 2025 20:43:53 -0700 Subject: [PATCH 3/9] fix gating to include Apple Clang 15 --- include/pybind11/pybind11.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 957d0d36c8..9e3acb9e10 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -277,7 +277,8 @@ class ReadableFunctionSignature { // Prior to C++17, we don't have inline variables, so we have to provide an out-of-line definition // of the class member. PYBIND11_WARNING_PUSH -#if defined(__clang_major__) && __clang_major__ >= 17 +#if defined(__clang_major__) \ + && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major >= 15)) PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") #endif template From d3db87b97d7237496f2204fc9683e5d153de3b5b Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 10 Oct 2025 10:49:29 -0700 Subject: [PATCH 4/9] Make GCC happy with types --- include/pybind11/pybind11.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 9e3acb9e10..1aa540a7fb 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -256,20 +256,23 @@ inline std::string generate_type_signature() { // cpp_function::initialize (which is templated on more types). template class ReadableFunctionSignature { +public: + using readable_signature_type = decltype(PYBIND11_READABLE_SIGNATURE_EXPR); + private: // We have to repeat PYBIND11_READABLE_SIGNATURE_EXPR in decltype() // because C++11 doesn't allow functions to return `auto`. (We don't // know the type because it's some variant of detail::descr with // unknown N.) - static constexpr decltype(PYBIND11_READABLE_SIGNATURE_EXPR) readable_signature() { + static constexpr readable_signature_type readable_signature() { return PYBIND11_READABLE_SIGNATURE_EXPR; } public: - static constexpr decltype(readable_signature()) kReadableSignature = readable_signature(); + static constexpr readable_signature_type kReadableSignature = readable_signature(); #if !defined(_MSC_VER) - static constexpr decltype(decltype(kReadableSignature)::types()) kTypes - = decltype(kReadableSignature)::types(); + using types_type = decltype(readable_signature_type::types()); + static constexpr types_type kTypes = readable_signature_type::types(); #endif }; #undef PYBIND11_READABLE_SIGNATURE_EXPR @@ -282,12 +285,11 @@ PYBIND11_WARNING_PUSH PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") #endif template -constexpr decltype(ReadableFunctionSignature::readable_signature()) +constexpr typename ReadableFunctionSignature::readable_signature_type ReadableFunctionSignature::kReadableSignature; #if !defined(_MSC_VER) template -constexpr decltype(decltype(ReadableFunctionSignature::kReadableSignature)::types()) +constexpr typename ReadableFunctionSignature::types_type ReadableFunctionSignature::kTypes; #endif PYBIND11_WARNING_POP From cb1027fabe8460dffc01d11aaaa39b191c343a0b Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 10 Oct 2025 13:54:01 -0700 Subject: [PATCH 5/9] fix apple clang gating again. suppress -Wdeprecated for GCC --- include/pybind11/pybind11.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 1aa540a7fb..06b5c21282 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -281,9 +281,10 @@ class ReadableFunctionSignature { // of the class member. PYBIND11_WARNING_PUSH #if defined(__clang_major__) \ - && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major >= 15)) + && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major__ >= 15)) PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") #endif +PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated") template constexpr typename ReadableFunctionSignature::readable_signature_type ReadableFunctionSignature::kReadableSignature; From c5cbec7870f5d54792184077c69592c75f25b1b0 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 10 Oct 2025 14:14:20 -0700 Subject: [PATCH 6/9] Gate warning suppressions to C++17. Suppress -Wdeprecated for clang as well. --- include/pybind11/pybind11.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 06b5c21282..5c698103e0 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -280,11 +280,14 @@ class ReadableFunctionSignature { // Prior to C++17, we don't have inline variables, so we have to provide an out-of-line definition // of the class member. PYBIND11_WARNING_PUSH -#if defined(__clang_major__) \ - && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major__ >= 15)) +#if defined(PYBIND11_CPP17) +# if defined(__clang_major__) \ + && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major__ >= 15)) PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") -#endif +# endif +PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated") PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated") +#endif template constexpr typename ReadableFunctionSignature::readable_signature_type ReadableFunctionSignature::kReadableSignature; From 98bee98daa2d44e73d3cf1724b89deb6a9fb6ac3 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 10 Oct 2025 15:02:47 -0700 Subject: [PATCH 7/9] hopefully fix last straggler CI job --- include/pybind11/pybind11.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 5c698103e0..fa2ca8fe75 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -283,6 +283,11 @@ PYBIND11_WARNING_PUSH #if defined(PYBIND11_CPP17) # if defined(__clang_major__) \ && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major__ >= 15)) +// Even with the above gating, there's one straggler CI job that +// claims it doesn't know what +// -Wdeprecated-redundant-constexpr-static-def is despite being on +// Apple Clang 15. Just suppress -Wunknown-warning-option. +PYBIND11_WARNING_DISABLE_CLANG("-Wunknown-warning-option") PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") # endif PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated") From 7af710e70fb7a9d07eb0378fbc71576d63334709 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 15 Oct 2025 11:30:43 -0700 Subject: [PATCH 8/9] attempt to address readability review feedback from @rwgk --- include/pybind11/pybind11.h | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index d7adcfbd81..8183b123b7 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -248,37 +248,40 @@ inline std::string generate_type_signature() { # define PYBIND11_COMPAT_STRDUP strdup #endif -#define PYBIND11_READABLE_SIGNATURE_EXPR \ +#define PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR \ detail::const_name("(") + cast_in::arg_names + detail::const_name(") -> ") + cast_out::name -// We centralize readable function signatures in a specific template -// so that we don't duplicate them across different instantiations of +// We factor out readable function signatures to a specific template +// so that they don't get duplicated across different instantiations of // cpp_function::initialize (which is templated on more types). template class ReadableFunctionSignature { public: - using readable_signature_type = decltype(PYBIND11_READABLE_SIGNATURE_EXPR); + using sig_type = decltype(PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR); private: - // We have to repeat PYBIND11_READABLE_SIGNATURE_EXPR in decltype() + // We have to repeat PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR in decltype() // because C++11 doesn't allow functions to return `auto`. (We don't // know the type because it's some variant of detail::descr with // unknown N.) - static constexpr readable_signature_type readable_signature() { - return PYBIND11_READABLE_SIGNATURE_EXPR; - } + static constexpr sig_type sig() { return PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR; } public: - static constexpr readable_signature_type kReadableSignature = readable_signature(); + static constexpr sig_type kSig = sig(); + // We can only stash the result of detail::descr::types() in a + // constexpr variable if we aren't on MSVC (see + // PYBIND11_DESCR_CONSTEXPR). #if !defined(_MSC_VER) - using types_type = decltype(readable_signature_type::types()); - static constexpr types_type kTypes = readable_signature_type::types(); + using types_type = decltype(sig_type::types()); + static constexpr types_type kTypes = sig_type::types(); #endif }; -#undef PYBIND11_READABLE_SIGNATURE_EXPR +#undef PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR -// Prior to C++17, we don't have inline variables, so we have to provide an out-of-line definition -// of the class member. +// Prior to C++17, we don't have inline variables, so we have to +// provide an out-of-line definition of the class member. We should +// remove the following chunk of code (until the PYBIND11_WARNING_POP) +// if/when we drop support for C++11 and C++14. PYBIND11_WARNING_PUSH #if defined(PYBIND11_CPP17) # if defined(__clang_major__) \ @@ -294,8 +297,8 @@ PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated") PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated") #endif template -constexpr typename ReadableFunctionSignature::readable_signature_type - ReadableFunctionSignature::kReadableSignature; +constexpr typename ReadableFunctionSignature::sig_type + ReadableFunctionSignature::kSig; #if !defined(_MSC_VER) template constexpr typename ReadableFunctionSignature::types_type @@ -537,7 +540,7 @@ class cpp_function : public function { /* Generate a readable signature describing the function's arguments and return value types */ static constexpr const auto &signature - = detail::ReadableFunctionSignature::kReadableSignature; + = detail::ReadableFunctionSignature::kSig; #if !defined(_MSC_VER) static constexpr const auto &types = detail::ReadableFunctionSignature::kTypes; From cc36bce80b599347367eab52b89753ed03422d96 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 15 Oct 2025 15:45:19 -0700 Subject: [PATCH 9/9] drop warning suppressions and instead just gate compilation the pre-C++17 compat code --- include/pybind11/pybind11.h | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 8183b123b7..8ab4681c76 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -279,32 +279,17 @@ class ReadableFunctionSignature { #undef PYBIND11_READABLE_FUNCTION_SIGNATURE_EXPR // Prior to C++17, we don't have inline variables, so we have to -// provide an out-of-line definition of the class member. We should -// remove the following chunk of code (until the PYBIND11_WARNING_POP) -// if/when we drop support for C++11 and C++14. -PYBIND11_WARNING_PUSH -#if defined(PYBIND11_CPP17) -# if defined(__clang_major__) \ - && (__clang_major__ >= 17 || (defined(__APPLE__) && __clang_major__ >= 15)) -// Even with the above gating, there's one straggler CI job that -// claims it doesn't know what -// -Wdeprecated-redundant-constexpr-static-def is despite being on -// Apple Clang 15. Just suppress -Wunknown-warning-option. -PYBIND11_WARNING_DISABLE_CLANG("-Wunknown-warning-option") -PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated-redundant-constexpr-static-def") -# endif -PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated") -PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated") -#endif +// provide an out-of-line definition of the class member. +#if !defined(PYBIND11_CPP17) template constexpr typename ReadableFunctionSignature::sig_type ReadableFunctionSignature::kSig; -#if !defined(_MSC_VER) +# if !defined(_MSC_VER) template constexpr typename ReadableFunctionSignature::types_type ReadableFunctionSignature::kTypes; +# endif #endif -PYBIND11_WARNING_POP PYBIND11_NAMESPACE_END(detail)