diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index e305066db7..50a3b87950 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -785,14 +785,22 @@ class type_caster_generic { // if we can find an exact match (or, for a simple C++ type, an inherited match); if // so, we can safely reinterpret_cast to the relevant pointer. if (bases.size() > 1) { + std::vector matching_bases; for (auto *base : bases) { if (no_cpp_mi ? PyType_IsSubtype(base->type, typeinfo->type) : base->type == typeinfo->type) { - this_.load_value( - reinterpret_cast(src.ptr())->get_value_and_holder(base)); - return true; + matching_bases.push_back(base); } } + if (matching_bases.size() != 0) { + if (matching_bases.size() > 1) { + matching_bases.push_back(const_cast(typeinfo)); + all_type_info_check_for_divergence(matching_bases); + } + this_.load_value(reinterpret_cast(src.ptr())->get_value_and_holder( + matching_bases[0])); + return true; + } } // Case 2c: C++ multiple inheritance is involved and we couldn't find an exact type diff --git a/tests/test_python_multiple_inheritance.cpp b/tests/test_python_multiple_inheritance.cpp index 664a2c23a0..15b1f3360e 100644 --- a/tests/test_python_multiple_inheritance.cpp +++ b/tests/test_python_multiple_inheritance.cpp @@ -61,4 +61,6 @@ TEST_SUBMODULE(python_multiple_inheritance, m) { .def("reset_drvd2_value", &CppDrvd2::reset_drvd2_value) .def("get_base_value_from_drvd2", &CppDrvd2::get_base_value_from_drvd2) .def("reset_base_value_from_drvd2", &CppDrvd2::reset_base_value_from_drvd2); + + m.def("pass_CppBase", [](const CppBase *) {}); } diff --git a/tests/test_python_multiple_inheritance.py b/tests/test_python_multiple_inheritance.py index 6669ac339e..6b941cb8d5 100644 --- a/tests/test_python_multiple_inheritance.py +++ b/tests/test_python_multiple_inheritance.py @@ -30,6 +30,12 @@ class PCD(PC1, PC2): pass +class PCDI(PC1, PC2): + def __init__(self): + PC1.__init__(self, 11) + PC2.__init__(self, 12) + + def test_PC(): d = PC(11) assert d.get_base_value() == 11 @@ -69,3 +75,9 @@ def test_PCD(): match=r"CppDrvd2\.__init__\(\) must be called when overriding __init__$", ): PCD(11) + + +def test_PCDI(): + obj = PCDI() + with pytest.raises(TypeError, match="^bases include diverging derived types: "): + m.pass_CppBase(obj)