Skip to content

Commit 6350bb3

Browse files
[mlir][py] Mark all type caster from_{cpp,python} methods as noexcept (#143866)
This is mentioned as a "must" in https://nanobind.readthedocs.io/en/latest/porting.html#type-casters when implementing type casters. While most of the existing `from_cpp` methods were already marked noexcept, many of the `from_python` methods were not. This commit adds the missing noexcept declarations to all type casters found in `NanobindAdaptors.h`. --------- Co-authored-by: Maksim Levental <[email protected]>
1 parent 2435ea6 commit 6350bb3

File tree

3 files changed

+66
-62
lines changed

3 files changed

+66
-62
lines changed

mlir/include/mlir/Bindings/Python/NanobindAdaptors.h

Lines changed: 56 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#define MLIR_BINDINGS_PYTHON_NANOBINDADAPTORS_H
2121

2222
#include <cstdint>
23+
#include <optional>
2324

2425
#include "mlir-c/Diagnostics.h"
2526
#include "mlir-c/IR.h"
@@ -43,18 +44,14 @@ namespace detail {
4344
/// with a raw handle (unowned). The returned object's lifetime may not extend
4445
/// beyond the apiObject handle without explicitly having its refcount increased
4546
/// (i.e. on return).
46-
static nanobind::object mlirApiObjectToCapsule(nanobind::handle apiObject) {
47+
static std::optional<nanobind::object>
48+
mlirApiObjectToCapsule(nanobind::handle apiObject) {
4749
if (PyCapsule_CheckExact(apiObject.ptr()))
4850
return nanobind::borrow<nanobind::object>(apiObject);
4951
nanobind::object api =
5052
nanobind::getattr(apiObject, MLIR_PYTHON_CAPI_PTR_ATTR, nanobind::none());
51-
if (api.is_none()) {
52-
std::string repr = nanobind::cast<std::string>(nanobind::repr(apiObject));
53-
throw nanobind::type_error(
54-
(llvm::Twine("Expected an MLIR object (got ") + repr + ").")
55-
.str()
56-
.c_str());
57-
}
53+
if (api.is_none())
54+
return {};
5855
return api;
5956
}
6057

@@ -67,12 +64,9 @@ static nanobind::object mlirApiObjectToCapsule(nanobind::handle apiObject) {
6764
template <>
6865
struct type_caster<MlirAffineMap> {
6966
NB_TYPE_CASTER(MlirAffineMap, const_name("MlirAffineMap"))
70-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
71-
nanobind::object capsule = mlirApiObjectToCapsule(src);
72-
value = mlirPythonCapsuleToAffineMap(capsule.ptr());
73-
if (mlirAffineMapIsNull(value)) {
74-
return false;
75-
}
67+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
68+
if (auto capsule = mlirApiObjectToCapsule(src))
69+
value = mlirPythonCapsuleToAffineMap(capsule->ptr());
7670
return !mlirAffineMapIsNull(value);
7771
}
7872
static handle from_cpp(MlirAffineMap v, rv_policy,
@@ -90,9 +84,9 @@ struct type_caster<MlirAffineMap> {
9084
template <>
9185
struct type_caster<MlirAttribute> {
9286
NB_TYPE_CASTER(MlirAttribute, const_name("MlirAttribute"))
93-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
94-
nanobind::object capsule = mlirApiObjectToCapsule(src);
95-
value = mlirPythonCapsuleToAttribute(capsule.ptr());
87+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
88+
if (auto capsule = mlirApiObjectToCapsule(src))
89+
value = mlirPythonCapsuleToAttribute(capsule->ptr());
9690
return !mlirAttributeIsNull(value);
9791
}
9892
static handle from_cpp(MlirAttribute v, rv_policy,
@@ -111,9 +105,9 @@ struct type_caster<MlirAttribute> {
111105
template <>
112106
struct type_caster<MlirBlock> {
113107
NB_TYPE_CASTER(MlirBlock, const_name("MlirBlock"))
114-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
115-
nanobind::object capsule = mlirApiObjectToCapsule(src);
116-
value = mlirPythonCapsuleToBlock(capsule.ptr());
108+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
109+
if (auto capsule = mlirApiObjectToCapsule(src))
110+
value = mlirPythonCapsuleToBlock(capsule->ptr());
117111
return !mlirBlockIsNull(value);
118112
}
119113
};
@@ -122,7 +116,7 @@ struct type_caster<MlirBlock> {
122116
template <>
123117
struct type_caster<MlirContext> {
124118
NB_TYPE_CASTER(MlirContext, const_name("MlirContext"))
125-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
119+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
126120
if (src.is_none()) {
127121
// Gets the current thread-bound context.
128122
// TODO: This raises an error of "No current context" currently.
@@ -132,8 +126,8 @@ struct type_caster<MlirContext> {
132126
.attr("Context")
133127
.attr("current");
134128
}
135-
nanobind::object capsule = mlirApiObjectToCapsule(src);
136-
value = mlirPythonCapsuleToContext(capsule.ptr());
129+
std::optional<nanobind::object> capsule = mlirApiObjectToCapsule(src);
130+
value = mlirPythonCapsuleToContext(capsule->ptr());
137131
return !mlirContextIsNull(value);
138132
}
139133
};
@@ -142,9 +136,9 @@ struct type_caster<MlirContext> {
142136
template <>
143137
struct type_caster<MlirDialectRegistry> {
144138
NB_TYPE_CASTER(MlirDialectRegistry, const_name("MlirDialectRegistry"))
145-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
146-
nanobind::object capsule = mlirApiObjectToCapsule(src);
147-
value = mlirPythonCapsuleToDialectRegistry(capsule.ptr());
139+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
140+
if (auto capsule = mlirApiObjectToCapsule(src))
141+
value = mlirPythonCapsuleToDialectRegistry(capsule->ptr());
148142
return !mlirDialectRegistryIsNull(value);
149143
}
150144
static handle from_cpp(MlirDialectRegistry v, rv_policy,
@@ -162,15 +156,15 @@ struct type_caster<MlirDialectRegistry> {
162156
template <>
163157
struct type_caster<MlirLocation> {
164158
NB_TYPE_CASTER(MlirLocation, const_name("MlirLocation"))
165-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
159+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
166160
if (src.is_none()) {
167161
// Gets the current thread-bound context.
168162
src = nanobind::module_::import_(MAKE_MLIR_PYTHON_QUALNAME("ir"))
169163
.attr("Location")
170164
.attr("current");
171165
}
172-
nanobind::object capsule = mlirApiObjectToCapsule(src);
173-
value = mlirPythonCapsuleToLocation(capsule.ptr());
166+
if (auto capsule = mlirApiObjectToCapsule(src))
167+
value = mlirPythonCapsuleToLocation(capsule->ptr());
174168
return !mlirLocationIsNull(value);
175169
}
176170
static handle from_cpp(MlirLocation v, rv_policy,
@@ -188,9 +182,9 @@ struct type_caster<MlirLocation> {
188182
template <>
189183
struct type_caster<MlirModule> {
190184
NB_TYPE_CASTER(MlirModule, const_name("MlirModule"))
191-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
192-
nanobind::object capsule = mlirApiObjectToCapsule(src);
193-
value = mlirPythonCapsuleToModule(capsule.ptr());
185+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
186+
if (auto capsule = mlirApiObjectToCapsule(src))
187+
value = mlirPythonCapsuleToModule(capsule->ptr());
194188
return !mlirModuleIsNull(value);
195189
}
196190
static handle from_cpp(MlirModule v, rv_policy,
@@ -209,12 +203,13 @@ template <>
209203
struct type_caster<MlirFrozenRewritePatternSet> {
210204
NB_TYPE_CASTER(MlirFrozenRewritePatternSet,
211205
const_name("MlirFrozenRewritePatternSet"))
212-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
213-
nanobind::object capsule = mlirApiObjectToCapsule(src);
214-
value = mlirPythonCapsuleToFrozenRewritePatternSet(capsule.ptr());
206+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
207+
if (auto capsule = mlirApiObjectToCapsule(src))
208+
value = mlirPythonCapsuleToFrozenRewritePatternSet(capsule->ptr());
215209
return value.ptr != nullptr;
216210
}
217-
static handle from_cpp(MlirFrozenRewritePatternSet v, rv_policy, handle) {
211+
static handle from_cpp(MlirFrozenRewritePatternSet v, rv_policy,
212+
handle) noexcept {
218213
nanobind::object capsule = nanobind::steal<nanobind::object>(
219214
mlirPythonFrozenRewritePatternSetToCapsule(v));
220215
return nanobind::module_::import_(MAKE_MLIR_PYTHON_QUALNAME("rewrite"))
@@ -228,9 +223,9 @@ struct type_caster<MlirFrozenRewritePatternSet> {
228223
template <>
229224
struct type_caster<MlirOperation> {
230225
NB_TYPE_CASTER(MlirOperation, const_name("MlirOperation"))
231-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
232-
nanobind::object capsule = mlirApiObjectToCapsule(src);
233-
value = mlirPythonCapsuleToOperation(capsule.ptr());
226+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
227+
if (auto capsule = mlirApiObjectToCapsule(src))
228+
value = mlirPythonCapsuleToOperation(capsule->ptr());
234229
return !mlirOperationIsNull(value);
235230
}
236231
static handle from_cpp(MlirOperation v, rv_policy,
@@ -250,9 +245,9 @@ struct type_caster<MlirOperation> {
250245
template <>
251246
struct type_caster<MlirValue> {
252247
NB_TYPE_CASTER(MlirValue, const_name("MlirValue"))
253-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
254-
nanobind::object capsule = mlirApiObjectToCapsule(src);
255-
value = mlirPythonCapsuleToValue(capsule.ptr());
248+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
249+
if (auto capsule = mlirApiObjectToCapsule(src))
250+
value = mlirPythonCapsuleToValue(capsule->ptr());
256251
return !mlirValueIsNull(value);
257252
}
258253
static handle from_cpp(MlirValue v, rv_policy,
@@ -273,9 +268,9 @@ struct type_caster<MlirValue> {
273268
template <>
274269
struct type_caster<MlirPassManager> {
275270
NB_TYPE_CASTER(MlirPassManager, const_name("MlirPassManager"))
276-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
277-
nanobind::object capsule = mlirApiObjectToCapsule(src);
278-
value = mlirPythonCapsuleToPassManager(capsule.ptr());
271+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
272+
if (auto capsule = mlirApiObjectToCapsule(src))
273+
value = mlirPythonCapsuleToPassManager(capsule->ptr());
279274
return !mlirPassManagerIsNull(value);
280275
}
281276
};
@@ -284,9 +279,9 @@ struct type_caster<MlirPassManager> {
284279
template <>
285280
struct type_caster<MlirTypeID> {
286281
NB_TYPE_CASTER(MlirTypeID, const_name("MlirTypeID"))
287-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
288-
nanobind::object capsule = mlirApiObjectToCapsule(src);
289-
value = mlirPythonCapsuleToTypeID(capsule.ptr());
282+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
283+
if (auto capsule = mlirApiObjectToCapsule(src))
284+
value = mlirPythonCapsuleToTypeID(capsule->ptr());
290285
return !mlirTypeIDIsNull(value);
291286
}
292287
static handle from_cpp(MlirTypeID v, rv_policy,
@@ -306,9 +301,9 @@ struct type_caster<MlirTypeID> {
306301
template <>
307302
struct type_caster<MlirType> {
308303
NB_TYPE_CASTER(MlirType, const_name("MlirType"))
309-
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) {
310-
nanobind::object capsule = mlirApiObjectToCapsule(src);
311-
value = mlirPythonCapsuleToType(capsule.ptr());
304+
bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept {
305+
if (auto capsule = mlirApiObjectToCapsule(src))
306+
value = mlirPythonCapsuleToType(capsule->ptr());
312307
return !mlirTypeIsNull(value);
313308
}
314309
static handle from_cpp(MlirType t, rv_policy,
@@ -462,9 +457,10 @@ class mlir_attribute_subclass : public pure_subclass {
462457
nanobind::object newCf = nanobind::cpp_function(
463458
[superCls, isaFunction, captureTypeName](
464459
nanobind::object cls, nanobind::object otherAttribute) {
465-
MlirAttribute rawAttribute =
466-
nanobind::cast<MlirAttribute>(otherAttribute);
467-
if (!isaFunction(rawAttribute)) {
460+
MlirAttribute rawAttribute;
461+
if (!nanobind::try_cast<MlirAttribute>(otherAttribute,
462+
rawAttribute) ||
463+
!isaFunction(rawAttribute)) {
468464
auto origRepr =
469465
nanobind::cast<std::string>(nanobind::repr(otherAttribute));
470466
throw std::invalid_argument(
@@ -543,8 +539,9 @@ class mlir_type_subclass : public pure_subclass {
543539
nanobind::object newCf = nanobind::cpp_function(
544540
[superCls, isaFunction, captureTypeName](nanobind::object cls,
545541
nanobind::object otherType) {
546-
MlirType rawType = nanobind::cast<MlirType>(otherType);
547-
if (!isaFunction(rawType)) {
542+
MlirType rawType;
543+
if (!nanobind::try_cast<MlirType>(otherType, rawType) ||
544+
!isaFunction(rawType)) {
548545
auto origRepr =
549546
nanobind::cast<std::string>(nanobind::repr(otherType));
550547
throw std::invalid_argument((llvm::Twine("Cannot cast type to ") +
@@ -625,8 +622,9 @@ class mlir_value_subclass : public pure_subclass {
625622
nanobind::object newCf = nanobind::cpp_function(
626623
[superCls, isaFunction, captureValueName](nanobind::object cls,
627624
nanobind::object otherValue) {
628-
MlirValue rawValue = nanobind::cast<MlirValue>(otherValue);
629-
if (!isaFunction(rawValue)) {
625+
MlirValue rawValue;
626+
if (!nanobind::try_cast<MlirValue>(otherValue, rawValue) ||
627+
!isaFunction(rawValue)) {
630628
auto origRepr =
631629
nanobind::cast<std::string>(nanobind::repr(otherValue));
632630
throw std::invalid_argument((llvm::Twine("Cannot cast value to ") +

mlir/test/python/dialects/python_test.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,9 @@ def testCustomAttribute():
361361
try:
362362
TestAttr(42)
363363
except TypeError as e:
364-
assert "Expected an MLIR object" in str(e)
364+
assert "Expected an MLIR object (got 42)" in str(e)
365+
except ValueError as e:
366+
assert "Cannot cast attribute to TestAttr (from 42)" in str(e)
365367
else:
366368
raise
367369

@@ -406,7 +408,9 @@ def testCustomType():
406408
try:
407409
TestType(42)
408410
except TypeError as e:
409-
assert "Expected an MLIR object" in str(e)
411+
assert "Expected an MLIR object (got 42)" in str(e)
412+
except ValueError as e:
413+
assert "Cannot cast type to TestType (from 42)" in str(e)
410414
else:
411415
raise
412416

mlir/test/python/lib/PythonTestModuleNanobind.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ NB_MODULE(_mlirPythonTestNanobind, m) {
113113
.attr(MLIR_PYTHON_CAPI_VALUE_CASTER_REGISTER_ATTR)(
114114
mlirRankedTensorTypeID)(
115115
nanobind::cpp_function([valueCls](const nb::object &valueObj) {
116-
nb::object capsule = mlirApiObjectToCapsule(valueObj);
117-
MlirValue v = mlirPythonCapsuleToValue(capsule.ptr());
116+
std::optional<nb::object> capsule =
117+
mlirApiObjectToCapsule(valueObj);
118+
assert(capsule.has_value() && "capsule is not null");
119+
MlirValue v = mlirPythonCapsuleToValue(capsule.value().ptr());
118120
MlirType t = mlirValueGetType(v);
119121
// This is hyper-specific in order to exercise/test registering a
120122
// value caster from cpp (but only for a single test case; see

0 commit comments

Comments
 (0)