From 891b0a12b4c188b73128fa3c0710d69d5a3bca33 Mon Sep 17 00:00:00 2001 From: Alecto Irene Perez Date: Wed, 14 Feb 2024 13:46:30 -0500 Subject: [PATCH] test(enum): add test for for #5020: silent conversion to float Enums (including enum class) are silently converted to floats during method calls. This can cause overload resolution to fail. I believe this behavior is a bug. This commit adds tests for that behavior. These tests fail right now, but they should pass once the behavior is fixed. See: https://github.com/pybind/pybind11/issues/5020 --- tests/test_enum.cpp | 10 ++++++++++ tests/test_enum.py | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/test_enum.cpp b/tests/test_enum.cpp index 2597b275e..0d9be6fc2 100644 --- a/tests/test_enum.cpp +++ b/tests/test_enum.cpp @@ -55,6 +55,16 @@ TEST_SUBMODULE(enums, m) { m.def("test_enum_to_uint", [](uint32_t) {}); m.def("test_enum_to_long_long", [](long long) {}); + // Trying to pass an enum to a function that accepts a float should + // trigger a type error + m.def("test_enum_to_float", [](double) {}); + + // When performing overload resolution, calling f(0, ScopedEnum.TWO) + // should select f(float, ScopedEnum), NOT f(float, float) + m.def("test_enum_overload_resolution", [](double, double) { return "f(float, float)"; }); + m.def("test_enum_overload_resolution", + [](double, ScopedEnum) { return "f(float, ScopedEnum)"; }); + // test_duplicate_enum_name enum SimpleEnum { ONE, TWO, THREE }; diff --git a/tests/test_enum.py b/tests/test_enum.py index 6b75b7ae5..68e15991a 100644 --- a/tests/test_enum.py +++ b/tests/test_enum.py @@ -229,6 +229,28 @@ def test_enum_to_int(): m.test_enum_to_long_long(m.ScopedBoolEnum.TRUE) +def test_enum_overload_resolution(): + """When performing overload resolution, enums should not be silently + converted to floats""" + assert m.test_enum_overload_resolution(0.0, 0.0) == "f(float, float)" + assert m.test_enum_overload_resolution(0, 0) == "f(float, float)" + assert ( + m.test_enum_overload_resolution(0.0, m.ScopedEnum.Two) == "f(float, ScopedEnum)" + ) + assert ( + m.test_enum_overload_resolution(0, m.ScopedEnum.Two) == "f(float, ScopedEnum)" + ) + + +def test_enum_to_float(): + """Passing an enum to a function taking a float should trigger a type error""" + with pytest.raises(TypeError) as execinfo: + m.test_enum_to_float(m.ScopedBoolEnum.TRUE) + assert str(execinfo.value).startswith( + "TypeError: test_enum_to_float(): incompatible function arguments." + ) + + def test_duplicate_enum_name(): with pytest.raises(ValueError) as excinfo: m.register_bad_enum()