@@ -180,6 +180,17 @@ extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name
180180 return PyType_Type.tp_getattro (obj, name);
181181}
182182
183+ // Band-aid workaround to fix a subtle but serious bug in a minimalistic fashion. See PR #4762.
184+ inline bool is_redundant_value_and_holder (const std::vector<type_info *> &bases,
185+ std::size_t ix_base) {
186+ for (std::size_t i = 0 ; i < ix_base; i++) {
187+ if (PyType_IsSubtype (bases[i]->type , bases[ix_base]->type ) != 0 ) {
188+ return true ;
189+ }
190+ }
191+ return false ;
192+ }
193+
183194// / metaclass `__call__` function that is used to create all pybind11 objects.
184195extern " C" inline PyObject *pybind11_meta_call (PyObject *type, PyObject *args, PyObject *kwargs) {
185196
@@ -189,18 +200,20 @@ extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, P
189200 return nullptr ;
190201 }
191202
192- // This must be a pybind11 instance
193- auto *instance = reinterpret_cast <detail::instance *>(self);
194-
195203 // Ensure that the base __init__ function(s) were called
196- for (const auto &vh : values_and_holders (instance)) {
197- if (!vh.holder_constructed ()) {
204+ const auto &bases = all_type_info ((PyTypeObject *) type);
205+ values_and_holders vhs (reinterpret_cast <detail::instance *>(self));
206+ assert (bases.size () == vhs.size ());
207+ std::size_t ix_base = 0 ;
208+ for (const auto &vh : vhs) {
209+ if (!vh.holder_constructed () && !is_redundant_value_and_holder (bases, ix_base)) {
198210 PyErr_Format (PyExc_TypeError,
199211 " %.200s.__init__() must be called when overriding __init__" ,
200212 get_fully_qualified_tp_name (vh.type ->type ).c_str ());
201213 Py_DECREF (self);
202214 return nullptr ;
203215 }
216+ ix_base++;
204217 }
205218
206219 return self;
0 commit comments