Skip to content

Commit 10a0e68

Browse files
committed
Remove unsound custom element example.
While we do check the array data element during extract, we do not check the type of the individual elements and hence there is no guarantee that they are of type T or even of uniform type. But if we did check each element, Python code having a reference the (base) array could change the elements and thereby their types after our check leading to type confusion in safe Rust code.
1 parent 54b14e0 commit 10a0e68

File tree

1 file changed

+5
-33
lines changed

1 file changed

+5
-33
lines changed

src/dtype.rs

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ impl PyArrayDescr {
292292

293293
/// Represents that a type can be an element of `PyArray`.
294294
///
295-
/// Currently, only integer/float/complex types are supported.
295+
/// Currently, only integer/float/complex/object types are supported.
296296
/// If you come up with a nice implementation for some other types, we're happy to receive your PR :)
297297
/// You may refer to the [numpy document](https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types)
298298
/// for all types that numpy supports.
@@ -310,38 +310,10 @@ impl PyArrayDescr {
310310
///
311311
/// # Custom element types
312312
///
313-
/// You can implement this trait to manage arrays of custom element types, but they still need to be stored
314-
/// on Python's heap using PyO3's [Py](pyo3::Py) type.
315-
///
316-
/// ```
317-
/// use numpy::{ndarray::Array2, Element, PyArray, PyArrayDescr, ToPyArray};
318-
/// use pyo3::{pyclass, Py, Python};
319-
///
320-
/// #[pyclass]
321-
/// pub struct CustomElement;
322-
///
323-
/// // The transparent wrapper is necessary as one cannot implement
324-
/// // a foreign trait (`Element`) on a foreign type (`Py`) directly.
325-
/// #[derive(Clone)]
326-
/// #[repr(transparent)]
327-
/// pub struct Wrapper(pub Py<CustomElement>);
328-
///
329-
/// unsafe impl Element for Wrapper {
330-
/// const IS_COPY: bool = false;
331-
///
332-
/// fn get_dtype(py: Python) -> &PyArrayDescr {
333-
/// PyArrayDescr::object(py)
334-
/// }
335-
/// }
336-
///
337-
/// Python::with_gil(|py| {
338-
/// let array = Array2::<Wrapper>::from_shape_fn((2, 3), |(_i, _j)| {
339-
/// Wrapper(Py::new(py, CustomElement).unwrap())
340-
/// });
341-
///
342-
/// let _array: &PyArray<Wrapper, _> = array.to_pyarray(py);
343-
/// });
344-
/// ```
313+
/// Note that we cannot safely store `Py<T>` where `T: PyClass`, because the type information would be
314+
/// eliminated in the resulting NumPy array.
315+
/// In other words, objects are always treated as `Py<PyAny>` (a.k.a. `PyObject`) by Python code,
316+
/// and only `Py<PyAny>` can be stored in a type safe manner.
345317
pub unsafe trait Element: Clone + Send {
346318
/// Flag that indicates whether this type is trivially copyable.
347319
///

0 commit comments

Comments
 (0)