From bdf6a5e8708abe87d42e0e4c8bef51db0f0957ff Mon Sep 17 00:00:00 2001 From: Hans Dembinski Date: Wed, 23 Oct 2019 12:19:58 +0100 Subject: [PATCH] Report type names in return value policy-related cast exceptions (#1965) --- include/pybind11/cast.h | 29 +++++++++++++++++++++++------ tests/test_copy_move.py | 6 +++--- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index efc10d65..e1bbf03a 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -533,9 +533,17 @@ public: case return_value_policy::copy: if (copy_constructor) valueptr = copy_constructor(src); - else - throw cast_error("return_value_policy = copy, but the " - "object is non-copyable!"); + else { +#if defined(NDEBUG) + throw cast_error("return_value_policy = copy, but type is " + "non-copyable! (compile in debug mode for details)"); +#else + std::string type_name(tinfo->cpptype->name()); + detail::clean_type_id(type_name); + throw cast_error("return_value_policy = copy, but type " + + type_name + " is non-copyable!"); +#endif + } wrapper->owned = true; break; @@ -544,9 +552,18 @@ public: valueptr = move_constructor(src); else if (copy_constructor) valueptr = copy_constructor(src); - else - throw cast_error("return_value_policy = move, but the " - "object is neither movable nor copyable!"); + else { +#if defined(NDEBUG) + throw cast_error("return_value_policy = move, but type is neither " + "movable nor copyable! " + "(compile in debug mode for details)"); +#else + std::string type_name(tinfo->cpptype->name()); + detail::clean_type_id(type_name); + throw cast_error("return_value_policy = move, but type " + + type_name + " is neither movable nor copyable!"); +#endif + } wrapper->owned = true; break; diff --git a/tests/test_copy_move.py b/tests/test_copy_move.py index aff2d99f..0e671d96 100644 --- a/tests/test_copy_move.py +++ b/tests/test_copy_move.py @@ -5,13 +5,13 @@ from pybind11_tests import copy_move_policies as m def test_lacking_copy_ctor(): with pytest.raises(RuntimeError) as excinfo: m.lacking_copy_ctor.get_one() - assert "the object is non-copyable!" in str(excinfo.value) + assert "is non-copyable!" in str(excinfo.value) def test_lacking_move_ctor(): with pytest.raises(RuntimeError) as excinfo: m.lacking_move_ctor.get_one() - assert "the object is neither movable nor copyable!" in str(excinfo.value) + assert "is neither movable nor copyable!" in str(excinfo.value) def test_move_and_copy_casts(): @@ -98,7 +98,7 @@ def test_private_op_new(): with pytest.raises(RuntimeError) as excinfo: m.private_op_new_value() - assert "the object is neither movable nor copyable" in str(excinfo.value) + assert "is neither movable nor copyable" in str(excinfo.value) assert m.private_op_new_reference().value == 1