Skip to content

Commit cb26e41

Browse files
committed
Make sure the shape/stride pointers live for long enough
1 parent 63f8d24 commit cb26e41

1 file changed

Lines changed: 27 additions & 12 deletions

File tree

src/ndarray.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,15 @@ where
190190
/* ndarray => DLPack */
191191
/*****************************************************************************/
192192

193-
fn array_to_tensor_view<T, D>(array: ndarray::ArrayView<'_, T, D>) -> Result<sys::DLTensor, DLPackNDarrayError> where
193+
fn array_to_tensor_view<'a, S, D, T>(array: &'a ndarray::ArrayBase<S, D>) -> Result<sys::DLTensor, DLPackNDarrayError> where
194194
D: ndarray::Dimension,
195+
S: ndarray::RawData<Elem = T>,
195196
T: GetDLPackDataType,
196197
{
197-
let shape = array.shape();
198-
let strides = ndarray::ArrayView::strides(&array);
198+
// SAFETY: we make sure that shape and strides are valid for the lifetime of
199+
// the array
200+
let shape: &'a [_] = array.shape();
201+
let strides: &'a[_] = ndarray::ArrayBase::strides(array);
199202

200203
// we need a `*const i64` for DLTensor, but we have usize and isize.
201204
// on 64-bit targets, isize will be the same as i64, so that's fine.
@@ -212,7 +215,6 @@ fn array_to_tensor_view<T, D>(array: ndarray::ArrayView<'_, T, D>) -> Result<sys
212215
let ndim = shape.len() as i32;
213216
let shape = shape.as_ptr().cast_mut().cast::<i64>();
214217

215-
216218
let device = sys::DLDevice {
217219
device_type: sys::DLDeviceType::kDLCPU,
218220
device_id: 0,
@@ -229,13 +231,13 @@ fn array_to_tensor_view<T, D>(array: ndarray::ArrayView<'_, T, D>) -> Result<sys
229231
});
230232
}
231233

232-
impl<'a, T, D> TryFrom<ndarray::ArrayView<'a, T, D>> for DLPackTensorRef<'a> where
234+
impl<'a, T, D> TryFrom<&'a ndarray::ArrayView<'a, T, D>> for DLPackTensorRef<'a> where
233235
D: ndarray::Dimension,
234236
T: GetDLPackDataType,
235237
{
236238
type Error = DLPackNDarrayError;
237239

238-
fn try_from(array: ndarray::ArrayView<'a, T, D>) -> Result<Self, Self::Error> {
240+
fn try_from(array: &'a ndarray::ArrayView<'a, T, D>) -> Result<Self, Self::Error> {
239241
let tensor = array_to_tensor_view(array)?;
240242

241243
return Ok(unsafe {
@@ -245,14 +247,14 @@ impl<'a, T, D> TryFrom<ndarray::ArrayView<'a, T, D>> for DLPackTensorRef<'a> whe
245247
}
246248
}
247249

248-
impl<'a, T, D> TryFrom<ndarray::ArrayViewMut<'a, T, D>> for DLPackTensorRefMut<'a> where
250+
impl<'a, T, D> TryFrom<&'a ndarray::ArrayViewMut<'a, T, D>> for DLPackTensorRefMut<'a> where
249251
D: ndarray::Dimension,
250252
T: GetDLPackDataType,
251253
{
252254
type Error = DLPackNDarrayError;
253255

254-
fn try_from(array: ndarray::ArrayViewMut<'a, T, D>) -> Result<Self, Self::Error> {
255-
let tensor = array_to_tensor_view(array.view())?;
256+
fn try_from(array: &'a ndarray::ArrayViewMut<'a, T, D>) -> Result<Self, Self::Error> {
257+
let tensor = array_to_tensor_view(array)?;
256258

257259
return Ok(unsafe {
258260
// SAFETY: we are constraining the lifetime of the return value, and
@@ -269,7 +271,13 @@ impl<'a, T, D> TryFrom<&'a ndarray::Array<T, D>> for DLPackTensorRef<'a> where
269271
type Error = DLPackNDarrayError;
270272

271273
fn try_from(array: &'a ndarray::Array<T, D>) -> Result<Self, Self::Error> {
272-
Self::try_from(array.view())
274+
let tensor = array_to_tensor_view(array)?;
275+
276+
return Ok(unsafe {
277+
// SAFETY: we are constraining the lifetime of the return value, and
278+
// returning a mut ref from a mut ref
279+
DLPackTensorRef::from_raw(tensor)
280+
});
273281
}
274282
}
275283

@@ -280,7 +288,13 @@ impl<'a, T, D> TryFrom<&'a mut ndarray::Array<T, D>> for DLPackTensorRefMut<'a>
280288
type Error = DLPackNDarrayError;
281289

282290
fn try_from(array: &'a mut ndarray::Array<T, D>) -> Result<Self, Self::Error> {
283-
Self::try_from(array.view_mut())
291+
let tensor = array_to_tensor_view(array)?;
292+
293+
return Ok(unsafe {
294+
// SAFETY: we are constraining the lifetime of the return value, and
295+
// returning a mut ref from a mut ref
296+
DLPackTensorRefMut::from_raw(tensor)
297+
});
284298
}
285299
}
286300

@@ -467,7 +481,8 @@ mod tests {
467481
#[test]
468482
fn test_ndarray_to_dlpack() {
469483
let array = arr2(&[[1i64, 2, 3], [4, 5, 6]]);
470-
let dlpack_ref = DLPackTensorRef::try_from(array.view()).unwrap();
484+
let view = array.view();
485+
let dlpack_ref = DLPackTensorRef::try_from(&view).unwrap();
471486
let raw = dlpack_ref.raw;
472487

473488
assert_eq!(raw.ndim, 2);

0 commit comments

Comments
 (0)