Skip to content

Unavoidable warnings with pybind11 main branch #31495

Closed

Description

@tacaswell

I am seeing warnings like

<ipython-input-4-1eb00ff78cf2>:1: MatplotlibDeprecationWarning: The x parameter as float was deprecated in Matplotlib 3.10 and will be removed in 3.12. Use int(x) instead.
  plt.show()
<ipython-input-4-1eb00ff78cf2>:1: MatplotlibDeprecationWarning: The y parameter as float was deprecated in Matplotlib 3.10 and will be removed in 3.12. Use int(y) instead.
  plt.show()

that come out on every draw ever for the simplest of plots (e.g. plt.gac(); plt.show()).

These are coming from

if (auto value = std::get_if<double>(&vx)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
"alternative"_a="int(x)");
x = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vx)) {
x = *value;
} else {
throw std::runtime_error("Should not happen");
}
if (auto value = std::get_if<double>(&vy)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
"alternative"_a="int(y)");
y = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vy)) {
y = *value;
} else {
throw std::runtime_error("Should not happen");
}

these warnings triggering are due to a change in pybind11 (only see this with their development branch) and which I bisected to

e8e8d6ab22f39938607f31d457d4d359c130f078 is the first bad commit
commit e8e8d6ab22f39938607f31d457d4d359c130f078
Author: Michael Carlstrom <rmc@carlstrom.com>
Date:   Mon Feb 16 23:00:01 2026 -0800

which came in via

if (auto value = std::get_if<double>(&vx)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
"alternative"_a="int(x)");
x = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vx)) {
x = *value;
} else {
throw std::runtime_error("Should not happen");
}
if (auto value = std::get_if<double>(&vy)) {
auto api = py::module_::import("matplotlib._api");
auto warn = api.attr("warn_deprecated");
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
"alternative"_a="int(y)");
y = static_cast<int>(*value);
} else if (auto value = std::get_if<int>(&vy)) {
y = *value;
} else {
throw std::runtime_error("Should not happen");
}

pybind/pybind11#5879

We either need to sort out how to adjust the pybind11 code or remove this warning.

Activity

  1. Chirag3841 commented on Apr 13, 2026

    @Chirag3841
    Contributor

    @tacaswell This seems to be caused by pybind11 resolving values as double, so std::get_if matches even for integers. We should either prioritize int over double in the variant handling or only warn when the float value is non-integral. Alternatively, fixing pybind11 to preserve integer types during casting would avoid this issue

  2. QuLogic commented on Apr 13, 2026

    @QuLogic
    Member

    Should we report an issue upstream first? From the upstream PR, this affects noconvert args as well, so I don't know how we'd modify the type conversion priority.

  3. tacaswell commented on Apr 14, 2026

    @tacaswell
    MemberAuthor

    I am not sure I have enough of a grasp on the problem to make a coherent upstream bug report nor the ability to write a minimal reproducer for them.

  4. QuLogic commented on Apr 16, 2026

    @QuLogic
    Member

    I wrote up a minimal reproducer:

    #include <pybind11/pybind11.h>
    #include <pybind11/stl.h>
    
    #include <variant>
    
    namespace py = pybind11;
    using namespace pybind11::literals;
    
    template <typename T>
    using double_or_ = std::variant<double, T>;
    
    static auto
    check_type(double_or_<int> var)
    {
        if (auto value = std::get_if<int>(&var)) {
            return "int";
        } else if (auto value = std::get_if<double>(&var)) {
            return "double";
        } else {
            // pybind11 will have only allowed types that match the variant, so this `else`
            // can't happen. We only have this case because older macOS doesn't support
            // `std::get` and using the conditional `std::get_if` means an `else` to silence
            // compiler warnings about "unhandled" cases.
            throw std::runtime_error("Should not happen");
        }
    }
    
    PYBIND11_MODULE(check, m)
    {
        m.def("check_type", &check_type, "var"_a.noconvert(true));
    }

    but as I was writing up the issue, I had an idea: if we swap the order of the std::variant, then hopefully pybind11 will pick the non-double option first, and it seems to have worked in my testing.

  5. added a commit that references this issue on Apr 16, 2026
    cb663c1
  6. added a commit that references this issue on Apr 16, 2026
    d6b33a2
  7. added this to the v3.10.9 milestone on Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions