diff --git a/src/data_repr.rs b/src/data_repr.rs index a24cd7789..4041c192b 100644 --- a/src/data_repr.rs +++ b/src/data_repr.rs @@ -59,11 +59,6 @@ impl OwnedRepr self.ptr.as_ptr() } - pub(crate) fn as_ptr_mut(&self) -> *mut A - { - self.ptr.as_ptr() - } - pub(crate) fn as_nonnull_mut(&mut self) -> NonNull { self.ptr diff --git a/src/impl_owned_array.rs b/src/impl_owned_array.rs index db176210c..44ac12dd4 100644 --- a/src/impl_owned_array.rs +++ b/src/impl_owned_array.rs @@ -1,9 +1,10 @@ #[cfg(not(feature = "std"))] use alloc::vec::Vec; +use core::ptr::NonNull; use std::mem; use std::mem::MaybeUninit; -#[allow(unused_imports)] +#[allow(unused_imports)] // Needed for Rust 1.64 use rawpointer::PointerExt; use crate::imp_prelude::*; @@ -435,7 +436,7 @@ where D: Dimension // "deconstruct" self; the owned repr releases ownership of all elements and we // carry on with raw view methods let data_len = self.data.len(); - let data_ptr = self.data.as_nonnull_mut().as_ptr(); + let data_ptr = self.data.as_nonnull_mut(); unsafe { // Safety: self.data releases ownership of the elements. Any panics below this point @@ -866,8 +867,9 @@ where D: Dimension /// /// This is an internal function for use by move_into and IntoIter only, safety invariants may need /// to be upheld across the calls from those implementations. -pub(crate) unsafe fn drop_unreachable_raw(mut self_: RawArrayViewMut, data_ptr: *mut A, data_len: usize) -where D: Dimension +pub(crate) unsafe fn drop_unreachable_raw( + mut self_: RawArrayViewMut, data_ptr: NonNull, data_len: usize, +) where D: Dimension { let self_len = self_.len(); @@ -878,7 +880,7 @@ where D: Dimension } sort_axes_in_default_order(&mut self_); // with uninverted axes this is now the element with lowest address - let array_memory_head_ptr = self_.ptr.as_ptr(); + let array_memory_head_ptr = self_.ptr; let data_end_ptr = data_ptr.add(data_len); debug_assert!(data_ptr <= array_memory_head_ptr); debug_assert!(array_memory_head_ptr <= data_end_ptr); @@ -907,7 +909,7 @@ where D: Dimension // iter is a raw pointer iterator traversing the array in memory order now with the // sorted axes. - let mut iter = Baseiter::new(self_.ptr.as_ptr(), self_.dim, self_.strides); + let mut iter = Baseiter::new(self_.ptr, self_.dim, self_.strides); let mut dropped_elements = 0; let mut last_ptr = data_ptr; @@ -917,7 +919,7 @@ where D: Dimension // should now be dropped. This interval may be empty, then we just skip this loop. while last_ptr != elem_ptr { debug_assert!(last_ptr < data_end_ptr); - std::ptr::drop_in_place(last_ptr); + std::ptr::drop_in_place(last_ptr.as_mut()); last_ptr = last_ptr.add(1); dropped_elements += 1; } @@ -926,7 +928,7 @@ where D: Dimension } while last_ptr < data_end_ptr { - std::ptr::drop_in_place(last_ptr); + std::ptr::drop_in_place(last_ptr.as_mut()); last_ptr = last_ptr.add(1); dropped_elements += 1; } diff --git a/src/impl_views/conversions.rs b/src/impl_views/conversions.rs index ef6923a56..1dd7d97f2 100644 --- a/src/impl_views/conversions.rs +++ b/src/impl_views/conversions.rs @@ -199,7 +199,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) } + unsafe { Baseiter::new(self.ptr, self.dim, self.strides) } } } @@ -209,7 +209,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) } + unsafe { Baseiter::new(self.ptr, self.dim, self.strides) } } } @@ -220,7 +220,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) } + unsafe { Baseiter::new(self.ptr, self.dim, self.strides) } } #[inline] @@ -262,7 +262,7 @@ where D: Dimension #[inline] pub(crate) fn into_base_iter(self) -> Baseiter { - unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) } + unsafe { Baseiter::new(self.ptr, self.dim, self.strides) } } #[inline] diff --git a/src/iterators/chunks.rs b/src/iterators/chunks.rs index 465428968..9e2f08e1e 100644 --- a/src/iterators/chunks.rs +++ b/src/iterators/chunks.rs @@ -204,7 +204,7 @@ impl_iterator! { fn item(&mut self, ptr) { unsafe { - ArrayView::new_( + ArrayView::new( ptr, self.chunk.clone(), self.inner_strides.clone()) @@ -226,7 +226,7 @@ impl_iterator! { fn item(&mut self, ptr) { unsafe { - ArrayViewMut::new_( + ArrayViewMut::new( ptr, self.chunk.clone(), self.inner_strides.clone()) diff --git a/src/iterators/into_iter.rs b/src/iterators/into_iter.rs index fcc2e4b8c..9374608cb 100644 --- a/src/iterators/into_iter.rs +++ b/src/iterators/into_iter.rs @@ -33,16 +33,15 @@ impl IntoIter where D: Dimension { /// Create a new by-value iterator that consumes `array` - pub(crate) fn new(mut array: Array) -> Self + pub(crate) fn new(array: Array) -> Self { unsafe { let array_head_ptr = array.ptr; - let ptr = array.as_mut_ptr(); let mut array_data = array.data; let data_len = array_data.release_all_elements(); debug_assert!(data_len >= array.dim.size()); let has_unreachable_elements = array.dim.size() != data_len; - let inner = Baseiter::new(ptr, array.dim, array.strides); + let inner = Baseiter::new(array_head_ptr, array.dim, array.strides); IntoIter { array_data, @@ -62,7 +61,7 @@ impl Iterator for IntoIter #[inline] fn next(&mut self) -> Option { - self.inner.next().map(|p| unsafe { p.read() }) + self.inner.next().map(|p| unsafe { p.as_ptr().read() }) } fn size_hint(&self) -> (usize, Option) @@ -92,7 +91,7 @@ where D: Dimension while let Some(_) = self.next() {} unsafe { - let data_ptr = self.array_data.as_ptr_mut(); + let data_ptr = self.array_data.as_nonnull_mut(); let view = RawArrayViewMut::new(self.array_head_ptr, self.inner.dim.clone(), self.inner.strides.clone()); debug_assert!(self.inner.dim.size() < self.data_len, "data_len {} and dim size {}", self.data_len, self.inner.dim.size()); diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index d49ffe2d0..e7321d15b 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -19,6 +19,10 @@ use alloc::vec::Vec; use std::iter::FromIterator; use std::marker::PhantomData; use std::ptr; +use std::ptr::NonNull; + +#[allow(unused_imports)] // Needed for Rust 1.64 +use rawpointer::PointerExt; use crate::Ix1; @@ -34,11 +38,11 @@ use std::slice::{self, Iter as SliceIter, IterMut as SliceIterMut}; /// Base for iterators over all axes. /// -/// Iterator element type is `*mut A`. +/// Iterator element type is `NonNull`. #[derive(Debug)] pub struct Baseiter { - ptr: *mut A, + ptr: NonNull, dim: D, strides: D, index: Option, @@ -50,7 +54,7 @@ impl Baseiter /// to be correct to avoid performing an unsafe pointer offset while /// iterating. #[inline] - pub unsafe fn new(ptr: *mut A, len: D, stride: D) -> Baseiter + pub unsafe fn new(ptr: NonNull, len: D, stride: D) -> Baseiter { Baseiter { ptr, @@ -63,10 +67,10 @@ impl Baseiter impl Iterator for Baseiter { - type Item = *mut A; + type Item = NonNull; #[inline] - fn next(&mut self) -> Option<*mut A> + fn next(&mut self) -> Option { let index = match self.index { None => return None, @@ -84,7 +88,7 @@ impl Iterator for Baseiter } fn fold(mut self, init: Acc, mut g: G) -> Acc - where G: FnMut(Acc, *mut A) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc { let ndim = self.dim.ndim(); debug_assert_ne!(ndim, 0); @@ -133,14 +137,14 @@ impl ExactSizeIterator for Baseiter impl DoubleEndedIterator for Baseiter { #[inline] - fn next_back(&mut self) -> Option<*mut A> + fn next_back(&mut self) -> Option { let index = match self.index { None => return None, Some(ix) => ix, }; self.dim[0] -= 1; - let offset = <_>::stride_offset(&self.dim, &self.strides); + let offset = Ix1::stride_offset(&self.dim, &self.strides); if index == self.dim { self.index = None; } @@ -148,13 +152,13 @@ impl DoubleEndedIterator for Baseiter unsafe { Some(self.ptr.offset(offset)) } } - fn nth_back(&mut self, n: usize) -> Option<*mut A> + fn nth_back(&mut self, n: usize) -> Option { let index = self.index?; let len = self.dim[0] - index[0]; if n < len { self.dim[0] -= n + 1; - let offset = <_>::stride_offset(&self.dim, &self.strides); + let offset = Ix1::stride_offset(&self.dim, &self.strides); if index == self.dim { self.index = None; } @@ -166,7 +170,7 @@ impl DoubleEndedIterator for Baseiter } fn rfold(mut self, init: Acc, mut g: G) -> Acc - where G: FnMut(Acc, *mut A) -> Acc + where G: FnMut(Acc, Self::Item) -> Acc { let mut accum = init; if let Some(index) = self.index { @@ -226,7 +230,7 @@ impl<'a, A, D: Dimension> Iterator for ElementsBase<'a, A, D> #[inline] fn next(&mut self) -> Option<&'a A> { - self.inner.next().map(|p| unsafe { &*p }) + self.inner.next().map(|p| unsafe { p.as_ref() }) } fn size_hint(&self) -> (usize, Option) @@ -237,7 +241,7 @@ impl<'a, A, D: Dimension> Iterator for ElementsBase<'a, A, D> fn fold(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc { - unsafe { self.inner.fold(init, move |acc, ptr| g(acc, &*ptr)) } + unsafe { self.inner.fold(init, move |acc, ptr| g(acc, ptr.as_ref())) } } } @@ -246,13 +250,13 @@ impl<'a, A> DoubleEndedIterator for ElementsBase<'a, A, Ix1> #[inline] fn next_back(&mut self) -> Option<&'a A> { - self.inner.next_back().map(|p| unsafe { &*p }) + self.inner.next_back().map(|p| unsafe { p.as_ref() }) } fn rfold(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc { - unsafe { self.inner.rfold(init, move |acc, ptr| g(acc, &*ptr)) } + unsafe { self.inner.rfold(init, move |acc, ptr| g(acc, ptr.as_ref())) } } } @@ -646,7 +650,7 @@ impl<'a, A, D: Dimension> Iterator for ElementsBaseMut<'a, A, D> #[inline] fn next(&mut self) -> Option<&'a mut A> { - self.inner.next().map(|p| unsafe { &mut *p }) + self.inner.next().map(|mut p| unsafe { p.as_mut() }) } fn size_hint(&self) -> (usize, Option) @@ -657,7 +661,10 @@ impl<'a, A, D: Dimension> Iterator for ElementsBaseMut<'a, A, D> fn fold(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc { - unsafe { self.inner.fold(init, move |acc, ptr| g(acc, &mut *ptr)) } + unsafe { + self.inner + .fold(init, move |acc, mut ptr| g(acc, ptr.as_mut())) + } } } @@ -666,13 +673,16 @@ impl<'a, A> DoubleEndedIterator for ElementsBaseMut<'a, A, Ix1> #[inline] fn next_back(&mut self) -> Option<&'a mut A> { - self.inner.next_back().map(|p| unsafe { &mut *p }) + self.inner.next_back().map(|mut p| unsafe { p.as_mut() }) } fn rfold(self, init: Acc, mut g: G) -> Acc where G: FnMut(Acc, Self::Item) -> Acc { - unsafe { self.inner.rfold(init, move |acc, ptr| g(acc, &mut *ptr)) } + unsafe { + self.inner + .rfold(init, move |acc, mut ptr| g(acc, ptr.as_mut())) + } } } @@ -748,7 +758,7 @@ where D: Dimension { self.iter .next() - .map(|ptr| unsafe { ArrayView::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) + .map(|ptr| unsafe { ArrayView::new(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) } fn size_hint(&self) -> (usize, Option) @@ -772,7 +782,7 @@ impl<'a, A> DoubleEndedIterator for LanesIter<'a, A, Ix1> { self.iter .next_back() - .map(|ptr| unsafe { ArrayView::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) + .map(|ptr| unsafe { ArrayView::new(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) } } @@ -800,7 +810,7 @@ where D: Dimension { self.iter .next() - .map(|ptr| unsafe { ArrayViewMut::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) + .map(|ptr| unsafe { ArrayViewMut::new(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) } fn size_hint(&self) -> (usize, Option) @@ -824,7 +834,7 @@ impl<'a, A> DoubleEndedIterator for LanesIterMut<'a, A, Ix1> { self.iter .next_back() - .map(|ptr| unsafe { ArrayViewMut::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) + .map(|ptr| unsafe { ArrayViewMut::new(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) }) } } diff --git a/src/iterators/windows.rs b/src/iterators/windows.rs index 453ef5024..1c2ab6a85 100644 --- a/src/iterators/windows.rs +++ b/src/iterators/windows.rs @@ -115,7 +115,7 @@ impl_iterator! { fn item(&mut self, ptr) { unsafe { - ArrayView::new_( + ArrayView::new( ptr, self.window.clone(), self.strides.clone()) diff --git a/tests/iterators.rs b/tests/iterators.rs index 23175fd40..908b64d15 100644 --- a/tests/iterators.rs +++ b/tests/iterators.rs @@ -1,6 +1,4 @@ -#![allow( - clippy::many_single_char_names, clippy::deref_addrof, clippy::unreadable_literal, clippy::many_single_char_names -)] +#![allow(clippy::deref_addrof, clippy::unreadable_literal)] use ndarray::prelude::*; use ndarray::{arr3, indices, s, Slice, Zip}; @@ -1055,3 +1053,33 @@ impl Drop for DropCount<'_> self.drops.set(self.drops.get() + 1); } } + +#[test] +fn test_impl_iter_compiles() +{ + // Requires that the iterators are covariant in the element type + + // base case: std + fn slice_iter_non_empty_indices<'s, 'a>(array: &'a Vec<&'s str>) -> impl Iterator + 'a + { + array + .iter() + .enumerate() + .filter(|(_index, elem)| !elem.is_empty()) + .map(|(index, _elem)| index) + } + + let _ = slice_iter_non_empty_indices; + + // ndarray case + fn array_iter_non_empty_indices<'s, 'a>(array: &'a Array<&'s str, Ix1>) -> impl Iterator + 'a + { + array + .iter() + .enumerate() + .filter(|(_index, elem)| !elem.is_empty()) + .map(|(index, _elem)| index) + } + + let _ = array_iter_non_empty_indices; +}