diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce0af35cfa..9e4dd5c2f59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ All notable changes to this project will be documented in this file. * added Python bindings for `SMT.SolverCall` and `SMT.Solver.to_smt2`, and the missing `Bitwuzla` value of `SMT.SolverType`. Without `SolverCall`, neither `QueryConfig.with_call` nor `Solver.has_local_solver_for` could be called at all although both were bound * fixed three enum values that were bound to a different value of their own enum, which made them indistinguishable from Python: `GateTypeProperty.fifo` was bound to `ram`, `module_identification.CandidateType.addition_offset` to `addition`, and `gui_extension_demo.ParameterType.Module` to `Gate` * added `to_string` and `__str__` to `SMT.QueryConfig`, `SMT.Constraint`, `SMT.Model` and `SMT.SolverResult`, printing any of them showed an object address before + * fixed every binding that carries the `hal::borrowed()` call policy segfaulting when it is called with arguments that its first overload does not accept, which happens with pybind11 3.1 and newer: the post-call hook is now also run for an overload whose arguments did not load and is handed a sentinel instead of an object. `Netlist.create_module` with a name, a parent, and a list of gates was the first such call in the binding smoke test, which is why the macOS CI, whose Homebrew pybind11 moved to 3.1.0 in September 2026, failed while the Ubuntu jobs on older pybind11 did not * Plugins * Boolean influence * fixed `get_ff_dependency_matrix` dereferencing an uninitialized pointer on every call, which segfaulted before it returned anything. The cache it passes on was never initialized, and a pointer that is not null passed the callee's check for one diff --git a/include/hal_core/python_bindings/python_bindings.h b/include/hal_core/python_bindings/python_bindings.h index 217eec29926..dc1a8a712e9 100644 --- a/include/hal_core/python_bindings/python_bindings.h +++ b/include/hal_core/python_bindings/python_bindings.h @@ -264,6 +264,13 @@ namespace pybind11 static void postcall(function_call& call, handle ret) { + // Since pybind11 3.1 the hook also runs for an overload whose arguments did not load, + // and is then handed the try-next-overload sentinel rather than an object. + if (!ret || ret.ptr() == PYBIND11_TRY_NEXT_OVERLOAD) + { + return; + } + // Only a method has a receiver worth falling back to. The first argument of a free // function is just an argument and need not own anything that is returned. // size(), not empty(): pybind11 changed args from a std::vector to a small_vector that has no empty()