From 8113a9caa36e74b78fb9804cf557abe33f0874cb Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Tue, 25 Aug 2026 14:26:29 +0300 Subject: [PATCH 1/2] Python: always pass the comment as a possibly-null pointer `cpp_function` is instantiated per set of pybind11 extras, so a function with a doc comment and an otherwise identical one without it got two separate instantiations. pybind11 treats a null `const char *` attribute exactly like an absent one (`process_attribute::init` just assigns it to `function_record::doc`), so passing the comment unconditionally - as null when there is none - collapses those two shapes into one. Applies to methods, free functions, fields and constructors. Worth -2.3% of `.text` on a synthetic module with a 50/50 mix of commented and uncommented entities, for no change in behavior: `pydoc` output, every `__doc__`, and every property's `fget`/`fset` docstrings are byte-identical. --- include/mrbind/targets/pybind11/core.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/include/mrbind/targets/pybind11/core.h b/include/mrbind/targets/pybind11/core.h index 2f409237..cf578b99 100644 --- a/include/mrbind/targets/pybind11/core.h +++ b/include/mrbind/targets/pybind11/core.h @@ -3669,6 +3669,9 @@ static_assert(std::is_same_v, float>, #define DETAIL_MB_PB11_CONV_OP_KIND_explicit() MRBind::pb11::FuncKind::conv_op_explicit // If the parameter is empty, returns `nullptr`. Otherwise prepends `+`. This is intended for optional comment strings, and `+` forces a conversion to a pointer, which helps reduce the number of instantiations. +// Prefer this over conditionally passing the comment at all: pybind11 treats a null `const char *` +// attribute exactly like an absent one, so always passing it keeps entities with and without a +// comment on the same `cpp_function` instantiation instead of doubling the shapes. #define DETAIL_MB_PB11_COMMENT_PTR(...) MRBIND_CAT(DETAIL_MB_PB11_COMMENT_PTR_, __VA_OPT__(1))(__VA_ARGS__) #define DETAIL_MB_PB11_COMMENT_PTR_(...) nullptr #define DETAIL_MB_PB11_COMMENT_PTR_1(...) +__VA_ARGS__ @@ -3756,8 +3759,8 @@ static_assert(std::is_same_v, float>, [](auto _pb11_f){_pb11_f(MRBIND_STRIP_LEADING_COMMA( \ /* Parameters. */\ DETAIL_MB_PB11_MAKE_PARAMS(params_) \ - /* Comment, if any. */ \ - MRBIND_PREPEND_COMMA(comment_) \ + /* Comment, possibly null. */ \ + , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_) \ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ));} \ @@ -3891,8 +3894,8 @@ static_assert(std::is_same_v, float>, _pb11_c,\ /* Name. */\ MRBind::pb11::ToPythonName(MRBIND_STR(MRBIND_IDENTITY fullname_)).c_str()\ - /* Comment, if any. */\ - DETAIL_MB_PB11_PREPEND_COMMA_PLUS(comment_)\ + /* Comment, possibly null. */\ + , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_)\ ); \ /* Add `offsetof` static variables. */\ MRBIND_CAT(DETAIL_MB_PB11_DISPATCH_MEMBER_field_OFFSETOF_,static_)(qualname_, name_) \ @@ -3924,8 +3927,8 @@ static_assert(std::is_same_v, float>, &_pb11_state.func_scope_state, _pb11_state.pass_number \ /* Parameters. */\ DETAIL_MB_PB11_MAKE_PARAMS(params_) \ - /* Comment, if any. */\ - DETAIL_MB_PB11_PREPEND_COMMA_PLUS(comment_) \ + /* Comment, possibly null. */\ + , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_)\ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ); @@ -3961,8 +3964,8 @@ static_assert(std::is_same_v, float>, [](auto _pb11_f){_pb11_f(MRBIND_STRIP_LEADING_COMMA( \ /* Parameters. */\ DETAIL_MB_PB11_MAKE_PARAMS(params_) \ - /* Comment, if any. */ \ - MRBIND_PREPEND_COMMA(comment_) \ + /* Comment, possibly null. */ \ + , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_) \ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ));} \ From 8e4f8bed5765e2e1c43f944f1bee298073a89424 Mon Sep 17 00:00:00 2001 From: Egor Mikhaylov Date: Tue, 25 Aug 2026 08:44:35 -0500 Subject: [PATCH 2/2] Tweak the implementation a bit. Update the note on AI usage. --- README.md | 2 +- include/mrbind/targets/pybind11/core.h | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index b71d8089..5062fe7a 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ MRBind is meant to cover a large API surface area with minimal effort, but in tu All MRBind features were developed without any use of AI. -I received some trivial vibecoded bugfix PRs that were merged after manual cleanup (which among other things includes replacing generated comments). I've also merged some generated testcases for those bugs. +I received some simple vibecoded contributions (bugfixes, binary size reductions) that were merged after manual cleanup, which among other things includes replacing the generated comments. I've also merged some generated testcases for those bugs. ## Usage diff --git a/include/mrbind/targets/pybind11/core.h b/include/mrbind/targets/pybind11/core.h index cf578b99..196b889e 100644 --- a/include/mrbind/targets/pybind11/core.h +++ b/include/mrbind/targets/pybind11/core.h @@ -3668,12 +3668,12 @@ static_assert(std::is_same_v, float>, #define DETAIL_MB_PB11_CONV_OP_KIND_() MRBind::pb11::FuncKind::conv_op #define DETAIL_MB_PB11_CONV_OP_KIND_explicit() MRBind::pb11::FuncKind::conv_op_explicit -// If the parameter is empty, returns `nullptr`. Otherwise prepends `+`. This is intended for optional comment strings, and `+` forces a conversion to a pointer, which helps reduce the number of instantiations. -// Prefer this over conditionally passing the comment at all: pybind11 treats a null `const char *` -// attribute exactly like an absent one, so always passing it keeps entities with and without a -// comment on the same `cpp_function` instantiation instead of doubling the shapes. +// If the parameter is empty, returns `(const char *)nullptr`. Otherwise prepends `+`. This is intended for optional comment strings, and `+` forces a conversion to a pointer, which helps reduce the number of instantiations. +// The cast on `nullptr` is there for the same reason, to reduce the number of instantiations. +// It's good to use this macro instead of conditionally passing the comment, since it too reduces the number of instantiations, +// and Pybind apparently treats the null pointers as if no comment was passed at all. #define DETAIL_MB_PB11_COMMENT_PTR(...) MRBIND_CAT(DETAIL_MB_PB11_COMMENT_PTR_, __VA_OPT__(1))(__VA_ARGS__) -#define DETAIL_MB_PB11_COMMENT_PTR_(...) nullptr +#define DETAIL_MB_PB11_COMMENT_PTR_(...) ((const char *)nullptr) #define DETAIL_MB_PB11_COMMENT_PTR_1(...) +__VA_ARGS__ // Returns the "namespace marker" class for the given namespace stack. @@ -3758,9 +3758,9 @@ static_assert(std::is_same_v, float>, /* Pybind extras: */\ [](auto _pb11_f){_pb11_f(MRBIND_STRIP_LEADING_COMMA( \ /* Parameters. */\ - DETAIL_MB_PB11_MAKE_PARAMS(params_) \ + DETAIL_MB_PB11_MAKE_PARAMS(params_), \ /* Comment, possibly null. */ \ - , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_) \ + DETAIL_MB_PB11_COMMENT_PTR(comment_) \ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ));} \ @@ -3893,9 +3893,9 @@ static_assert(std::is_same_v, float>, >(\ _pb11_c,\ /* Name. */\ - MRBind::pb11::ToPythonName(MRBIND_STR(MRBIND_IDENTITY fullname_)).c_str()\ + MRBind::pb11::ToPythonName(MRBIND_STR(MRBIND_IDENTITY fullname_)).c_str(),\ /* Comment, possibly null. */\ - , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_)\ + DETAIL_MB_PB11_COMMENT_PTR(comment_)\ ); \ /* Add `offsetof` static variables. */\ MRBIND_CAT(DETAIL_MB_PB11_DISPATCH_MEMBER_field_OFFSETOF_,static_)(qualname_, name_) \ @@ -3926,9 +3926,9 @@ static_assert(std::is_same_v, float>, _pb11_c, \ &_pb11_state.func_scope_state, _pb11_state.pass_number \ /* Parameters. */\ - DETAIL_MB_PB11_MAKE_PARAMS(params_) \ + DETAIL_MB_PB11_MAKE_PARAMS(params_), \ /* Comment, possibly null. */\ - , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_)\ + DETAIL_MB_PB11_COMMENT_PTR(comment_)\ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ); @@ -3963,9 +3963,9 @@ static_assert(std::is_same_v, float>, /* Pybind extras: */\ [](auto _pb11_f){_pb11_f(MRBIND_STRIP_LEADING_COMMA( \ /* Parameters. */\ - DETAIL_MB_PB11_MAKE_PARAMS(params_) \ + DETAIL_MB_PB11_MAKE_PARAMS(params_), \ /* Comment, possibly null. */ \ - , (const char *)DETAIL_MB_PB11_COMMENT_PTR(comment_) \ + DETAIL_MB_PB11_COMMENT_PTR(comment_) \ /* Lifetime annotations. */ \ DETAIL_MB_PB11_KEEP_ALIVE(lifetimes_) \ ));} \