diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b05bc7f0..967587643 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -502,7 +502,9 @@ jobs: - { gcc: 7, std: 17 } - { gcc: 8, std: 14 } - { gcc: 8, std: 17 } + - { gcc: 9, std: 20 } - { gcc: 10, std: 17 } + - { gcc: 10, std: 20 } - { gcc: 11, std: 20 } - { gcc: 12, std: 20 } - { gcc: 13, std: 20 } diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml index 8d0b516ee..143d58624 100644 --- a/.github/workflows/pip.yml +++ b/.github/workflows/pip.yml @@ -103,7 +103,7 @@ jobs: - uses: actions/download-artifact@v4 - name: Generate artifact attestation for sdist and wheel - uses: actions/attest-build-provenance@173725a1209d09b31f9d30a3890cf2757ebbff0d # v1.1.2 + uses: actions/attest-build-provenance@bdd51370e0416ac948727f861e03c2f05d32d78e # v1.3.2 with: subject-path: "*/pybind11*" diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index d2f577ad2..62ac54d60 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -770,6 +770,13 @@ class type_caster> : public tuple_caster {} template class type_caster> : public tuple_caster {}; +template <> +class type_caster> : public tuple_caster { +public: + // PEP 484 specifies this syntax for an empty tuple + static constexpr auto name = const_name("tuple[()]"); +}; + /// Helper class which abstracts away certain actions. Users can provide specializations for /// custom holders, but it's only necessary if the type has a non-standard interface. template diff --git a/include/pybind11/typing.h b/include/pybind11/typing.h index 1442cdc7f..b0feb9464 100644 --- a/include/pybind11/typing.h +++ b/include/pybind11/typing.h @@ -14,6 +14,8 @@ #include "cast.h" #include "pytypes.h" +#include + PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(typing) @@ -98,7 +100,10 @@ class Never : public none { using none::none; }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(__cpp_nontype_template_parameter_class) \ + && (/* See #5201 */ !defined(__GNUC__) \ + || (__GNUC__ > 10 || (__GNUC__ == 10 && __GNUC_MINOR__ >= 3))) +# define PYBIND11_TYPING_H_HAS_STRING_LITERAL template struct StringLiteral { constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, name); } @@ -222,7 +227,7 @@ struct handle_type_name { static constexpr auto name = const_name("Never"); }; -#if defined(__cpp_nontype_template_parameter_class) +#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) template struct handle_type_name> { static constexpr auto name = const_name("Literal[") diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py index 9aa5926e9..b37aacff1 100644 --- a/tests/test_builtin_casters.py +++ b/tests/test_builtin_casters.py @@ -368,6 +368,8 @@ def test_tuple(doc): """ ) + assert doc(m.empty_tuple) == """empty_tuple() -> tuple[()]""" + assert m.rvalue_pair() == ("rvalue", "rvalue") assert m.lvalue_pair() == ("lvalue", "lvalue") assert m.rvalue_tuple() == ("rvalue", "rvalue", "rvalue") diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp index 7c30978ce..ecb44939a 100644 --- a/tests/test_pytypes.cpp +++ b/tests/test_pytypes.cpp @@ -109,7 +109,7 @@ void m_defs(py::module_ &m) { } // namespace handle_from_move_only_type_with_operator_PyObject -#if defined(__cpp_nontype_template_parameter_class) +#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) namespace literals { enum Color { RED = 0, BLUE = 1 }; @@ -905,7 +905,7 @@ TEST_SUBMODULE(pytypes, m) { m.def("annotate_optional_to_object", [](py::typing::Optional &o) -> py::object { return o; }); -#if defined(__cpp_nontype_template_parameter_class) +#if defined(PYBIND11_TYPING_H_HAS_STRING_LITERAL) py::enum_(m, "Color") .value("RED", literals::Color::RED) .value("BLUE", literals::Color::BLUE); @@ -919,8 +919,8 @@ TEST_SUBMODULE(pytypes, m) { m.def("annotate_listT_to_T", [](const py::typing::List &l) -> typevar::TypeVarT { return l[0]; }); m.def("annotate_object_to_T", [](const py::object &o) -> typevar::TypeVarT { return o; }); - m.attr("if_defined__cpp_nontype_template_parameter_class") = true; + m.attr("defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL") = true; #else - m.attr("if_defined__cpp_nontype_template_parameter_class") = false; + m.attr("defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL") = false; #endif } diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 30931e0b9..218092b43 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -1025,7 +1025,7 @@ def test_optional_object_annotations(doc): @pytest.mark.skipif( - not m.if_defined__cpp_nontype_template_parameter_class, + not m.defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL, reason="C++20 feature not available.", ) def test_literal(doc): @@ -1036,7 +1036,7 @@ def test_literal(doc): @pytest.mark.skipif( - not m.if_defined__cpp_nontype_template_parameter_class, + not m.defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL, reason="C++20 feature not available.", ) def test_typevar(doc): diff --git a/tools/pybind11Common.cmake b/tools/pybind11Common.cmake index d8e18e67b..8467b45d2 100644 --- a/tools/pybind11Common.cmake +++ b/tools/pybind11Common.cmake @@ -335,7 +335,7 @@ function(_pybind11_generate_lto target prefer_thin_lto) set(PYBIND11_LTO_LINKER_FLAGS "-flto${thin}${linker_append}") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") _pybind11_return_if_cxx_and_linker_flags_work( - HAS_FLTO_THIN "-flto${thin}${cxx_append}" "-flto=${thin}${linker_append}" + HAS_FLTO_THIN "-flto${thin}${cxx_append}" "-flto${thin}${linker_append}" PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS) endif() if(NOT HAS_FLTO_THIN)