Fail static_assert when trying to reference non-referencable types
The previous commit to address #392 triggers a compiler warning about
returning a reference to a local variable, which is *not* a false alarm:
the following:
py::cast<int &>(o)
(which happens internally in an overload declaration) really is
returning a reference to a local, because the cast operators for the
type_caster for numeric types returns a reference to its own member.
This commit adds a static_assert to make that a compilation failure
rather than returning a reference into about-to-be-freed memory.
Incidentally, this is also a fix for #219, which is exactly the same
issue: we can't reference numeric primitives that are cast from
wrappers around python numeric types.
diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp
index 66ff79d..c4d89c1 100644
--- a/tests/test_issues.cpp
+++ b/tests/test_issues.cpp
@@ -208,7 +208,9 @@
public:
using OverrideTest::OverrideTest;
int int_value() override { PYBIND11_OVERLOAD(int, OverrideTest, int_value); }
- int &int_ref() override { PYBIND11_OVERLOAD(int &, OverrideTest, int_ref); }
+ // Not allowed (uncommenting should hit a static_assert failure): we can't get a reference
+ // to a python numeric value, since we only copy values in the numeric type caster:
+// int &int_ref() override { PYBIND11_OVERLOAD(int &, OverrideTest, int_ref); }
A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); }
A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); }
};
@@ -217,9 +219,10 @@
py::class_<OverrideTest, PyOverrideTest>(m2, "OverrideTest")
.def(py::init<int>())
.def("int_value", &OverrideTest::int_value)
- .def("int_ref", &OverrideTest::int_ref)
+// .def("int_ref", &OverrideTest::int_ref)
.def("A_value", &OverrideTest::A_value)
.def("A_ref", &OverrideTest::A_ref);
+
}
// MSVC workaround: trying to use a lambda here crashes MSCV
diff --git a/tests/test_issues.py b/tests/test_issues.py
index 056737a..86bd6a5 100644
--- a/tests/test_issues.py
+++ b/tests/test_issues.py
@@ -171,9 +171,10 @@
from pybind11_tests.issues import OverrideTest
o = OverrideTest(42)
- i = o.int_ref()
+ # Not allowed (see associated .cpp comment)
+ #i = o.int_ref()
+ #assert o.int_ref() == 42
assert o.int_value() == 42
- assert o.int_ref() == 42
assert o.A_value().value == 99
a = o.A_ref()