Fix potential crash when calling an overloaded function (#1327)
* Fix potential crash when calling an overloaded function
The crash would occur if:
- dispatcher() uses two-pass logic (because the target is overloaded and some arguments support conversions)
- the first pass (with conversions disabled) doesn't find any matching overload
- the second pass does find a matching overload, but its return value can't be converted to Python
The code for formatting the error message assumed `it` still pointed to the selected overload,
but during the second-pass loop `it` was nullptr. Fix by setting `it` correctly if a second-pass
call returns a nullptr `handle`. Add a new test that segfaults without this fix.
* Make overload iteration const-correct so we don't have to iterate again on second-pass error
* Change test_error_after_conversions dependencies to local classes/variables
diff --git a/tests/test_class.cpp b/tests/test_class.cpp
index 9265e2e..9ed1f50 100644
--- a/tests/test_class.cpp
+++ b/tests/test_class.cpp
@@ -341,6 +341,19 @@
"a"_a, "b"_a, "c"_a);
base.def("g", [](NestBase &, Nested &) {});
base.def("h", []() { return NestBase(); });
+
+ // test_error_after_conversion
+ // The second-pass path through dispatcher() previously didn't
+ // remember which overload was used, and would crash trying to
+ // generate a useful error message
+
+ struct NotRegistered {};
+ struct StringWrapper { std::string str; };
+ m.def("test_error_after_conversions", [](int) {});
+ m.def("test_error_after_conversions",
+ [](StringWrapper) -> NotRegistered { return {}; });
+ py::class_<StringWrapper>(m, "StringWrapper").def(py::init<std::string>());
+ py::implicitly_convertible<std::string, StringWrapper>();
}
template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };