[Mlir-commits] [mlir] [mlir][python] Fix Python binding cast diagnostics for nanobind 2.13 (PR #206391)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Jun 28 19:25:52 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Maksim Levental (makslevental)

<details>
<summary>Changes</summary>

Fixes #<!-- -->205329 

---
Full diff: https://github.com/llvm/llvm-project/pull/206391.diff


3 Files Affected:

- (modified) mlir/include/mlir/Bindings/Python/IRAttributes.h (+9-6) 
- (modified) mlir/lib/Bindings/Python/IRAffine.cpp (+27-24) 
- (modified) mlir/lib/Bindings/Python/IRCore.cpp (+9-7) 


``````````diff
diff --git a/mlir/include/mlir/Bindings/Python/IRAttributes.h b/mlir/include/mlir/Bindings/Python/IRAttributes.h
index 7f2f88b552453..376ff732c99a8 100644
--- a/mlir/include/mlir/Bindings/Python/IRAttributes.h
+++ b/mlir/include/mlir/Bindings/Python/IRAttributes.h
@@ -100,16 +100,19 @@ template <typename T>
 static T pyTryCast(nanobind::handle object) {
   try {
     return nanobind::cast<T>(object);
-  } catch (nanobind::cast_error &err) {
+  } catch (std::exception &err) {
+    // Decide the `None?` hint from the value, not the exception type, since
+    // nanobind >= 2.13 raises cast_error (std::bad_cast) for all failures.
+    if (object.is_none()) {
+      std::string msg = std::string("Invalid attribute (None?) when attempting "
+                                    "to create an ArrayAttribute (") +
+                        err.what() + ")";
+      throw std::runtime_error(msg.c_str());
+    }
     std::string msg = std::string("Invalid attribute when attempting to "
                                   "create an ArrayAttribute (") +
                       err.what() + ")";
     throw std::runtime_error(msg.c_str());
-  } catch (std::runtime_error &err) {
-    std::string msg = std::string("Invalid attribute (None?) when attempting "
-                                  "to create an ArrayAttribute (") +
-                      err.what() + ")";
-    throw std::runtime_error(msg.c_str());
   }
 }
 
diff --git a/mlir/lib/Bindings/Python/IRAffine.cpp b/mlir/lib/Bindings/Python/IRAffine.cpp
index 07aa4759bae5f..d6f4a514a841b 100644
--- a/mlir/lib/Bindings/Python/IRAffine.cpp
+++ b/mlir/lib/Bindings/Python/IRAffine.cpp
@@ -43,14 +43,17 @@ static void pyListToVector(const nb::sequence &list, std::vector<CType> &result,
   for (nb::handle item : list) {
     try {
       result.push_back(nb::cast<PyType>(item));
-    } catch (nb::cast_error &err) {
+    } catch (std::exception &err) {
+      // Decide the `None?` hint from the value, not the exception type, since
+      // nanobind >= 2.13 raises cast_error (std::bad_cast) for all failures.
+      if (item.is_none()) {
+        std::string msg = nanobind::detail::join(
+            "Invalid expression (None?) when ", action, " (", err.what(), ")");
+        throw std::runtime_error(msg.c_str());
+      }
       std::string msg = nanobind::detail::join("Invalid expression when ",
                                                action, " (", err.what(), ")");
       throw std::runtime_error(msg.c_str());
-    } catch (std::runtime_error &err) {
-      std::string msg = nanobind::detail::join(
-          "Invalid expression (None?) when ", action, " (", err.what(), ")");
-      throw std::runtime_error(msg.c_str());
     }
   }
 }
@@ -731,25 +734,25 @@ void populateIRAffine(nb::module_ &m) {
            [](PyAffineMap &self) {
              return std::hash<const void *>{}(self.get().ptr);
            })
-      .def_static(
-          "compress_unused_symbols",
-          [](nb::typed<nb::sequence, PyAffineMap> affineMaps,
-             DefaultingPyMlirContext context) {
-            std::vector<MlirAffineMap> maps;
-            pyListToVector<PyAffineMap, MlirAffineMap>(
-                affineMaps, maps, "attempting to create an AffineMap");
-            std::vector<MlirAffineMap> compressed(nb::len(affineMaps));
-            auto populate = [](void *result, intptr_t idx, MlirAffineMap m) {
-              static_cast<MlirAffineMap *>(result)[idx] = (m);
-            };
-            mlirAffineMapCompressUnusedSymbols(maps.data(), maps.size(),
-                                               compressed.data(), populate);
-            std::vector<PyAffineMap> res;
-            res.reserve(compressed.size());
-            for (auto m : compressed)
-              res.emplace_back(context->getRef(), m);
-            return res;
-          })
+      .def_static("compress_unused_symbols",
+                  [](nb::typed<nb::sequence, PyAffineMap> affineMaps,
+                     DefaultingPyMlirContext context) {
+                    std::vector<MlirAffineMap> maps;
+                    pyListToVector<PyAffineMap, MlirAffineMap>(
+                        affineMaps, maps, "attempting to create an AffineMap");
+                    std::vector<MlirAffineMap> compressed(nb::len(affineMaps));
+                    auto populate = [](void *result, intptr_t idx,
+                                       MlirAffineMap m) {
+                      static_cast<MlirAffineMap *>(result)[idx] = (m);
+                    };
+                    mlirAffineMapCompressUnusedSymbols(
+                        maps.data(), maps.size(), compressed.data(), populate);
+                    std::vector<PyAffineMap> res;
+                    res.reserve(compressed.size());
+                    for (auto m : compressed)
+                      res.emplace_back(context->getRef(), m);
+                    return res;
+                  })
       .def_prop_ro(
           "context",
           [](PyAffineMap &self) -> nb::typed<nb::object, PyMlirContext> {
diff --git a/mlir/lib/Bindings/Python/IRCore.cpp b/mlir/lib/Bindings/Python/IRCore.cpp
index fc69ef8884466..96d596f8b5151 100644
--- a/mlir/lib/Bindings/Python/IRCore.cpp
+++ b/mlir/lib/Bindings/Python/IRCore.cpp
@@ -1272,17 +1272,19 @@ nb::object PyOperation::create(std::string_view name,
         auto &attribute = nb::cast<PyAttribute &>(it.second);
         // TODO: Verify attribute originates from the same context.
         mlirAttributes.emplace_back(std::move(key), attribute);
-      } catch (nb::cast_error &err) {
+      } catch (std::exception &err) {
+        // Decide the `None` hint from the value, not the exception type, since
+        // nanobind >= 2.13 raises cast_error (std::bad_cast) for all failures.
+        if (it.second.is_none()) {
+          std::string msg = join(
+              "Found an invalid (`None`?) attribute value for the key \"", key,
+              "\" when attempting to create the operation \"", name, "\"");
+          throw std::runtime_error(msg);
+        }
         std::string msg = join("Invalid attribute value for the key \"", key,
                                "\" when attempting to create the operation \"",
                                name, "\" (", err.what(), ")");
         throw nb::type_error(msg.c_str());
-      } catch (std::runtime_error &) {
-        // This exception seems thrown when the value is "None".
-        std::string msg = join(
-            "Found an invalid (`None`?) attribute value for the key \"", key,
-            "\" when attempting to create the operation \"", name, "\"");
-        throw std::runtime_error(msg);
       }
     }
   }

``````````

</details>


https://github.com/llvm/llvm-project/pull/206391


More information about the Mlir-commits mailing list