diff --git a/mlir/include/mlir/Bindings/Python/PybindAdaptors.h b/mlir/include/mlir/Bindings/Python/PybindAdaptors.h --- a/mlir/include/mlir/Bindings/Python/PybindAdaptors.h +++ b/mlir/include/mlir/Bindings/Python/PybindAdaptors.h @@ -42,13 +42,19 @@ /// an explicit Capsule (which can happen when two C APIs are communicating /// directly via Python) or indirectly by querying the MLIR_PYTHON_CAPI_PTR_ATTR /// attribute (through which supported MLIR Python API objects export their -/// contained API pointer as a capsule). This is intended to be used from -/// type casters, which are invoked with a raw handle (unowned). The returned -/// object's lifetime may not extend beyond the apiObject handle without -/// explicitly having its refcount increased (i.e. on return). +/// contained API pointer as a capsule). Throws a type error if the object is +/// neither. This is intended to be used from type casters, which are invoked +/// with a raw handle (unowned). The returned object's lifetime may not extend +/// beyond the apiObject handle without explicitly having its refcount increased +/// (i.e. on return). static py::object mlirApiObjectToCapsule(py::handle apiObject) { if (PyCapsule_CheckExact(apiObject.ptr())) return py::reinterpret_borrow(apiObject); + if (!py::hasattr(apiObject, MLIR_PYTHON_CAPI_PTR_ATTR)) { + auto repr = py::repr(apiObject).cast(); + throw py::type_error( + (llvm::Twine("Expected an MLIR object (got ") + repr + ").").str()); + } return apiObject.attr(MLIR_PYTHON_CAPI_PTR_ATTR); } diff --git a/mlir/test/python/dialects/python_test.py b/mlir/test/python/dialects/python_test.py --- a/mlir/test/python/dialects/python_test.py +++ b/mlir/test/python/dialects/python_test.py @@ -247,6 +247,15 @@ else: raise + # The following must trigger a TypeError from our adaptors and must not + # crash. + try: + test.TestAttr(42) + except TypeError as e: + assert "Expected an MLIR object" in str(e) + else: + raise + # The following must trigger a TypeError from pybind (therefore, not # checking its message) and must not crash. try: @@ -276,6 +285,15 @@ else: raise + # The following must trigger a TypeError from our adaptors and must not + # crash. + try: + test.TestType(42) + except TypeError as e: + assert "Expected an MLIR object" in str(e) + else: + raise + # The following must trigger a TypeError from pybind (therefore, not # checking its message) and must not crash. try: