diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index 024a1e3b4..25b0dc118 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -471,8 +471,9 @@ where /// ### Safety /// /// Accessing uninitalized values is undefined behaviour. You must - /// overwrite *all* the elements in the array after it is created; for - /// example using the methods `.fill()` or `.assign()`. + /// overwrite *all* the elements in the array after it is created; this must + /// be done carefully, for example using the methods `.fill()` or `.assign()`, + /// which are documented to support this use case. /// /// The contents of the array is indeterminate before initialization and it /// is an error to perform operations that use the previous values. For diff --git a/src/impl_methods.rs b/src/impl_methods.rs index db502663f..8c10db1eb 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -1909,6 +1909,9 @@ where /// /// If their shapes disagree, `rhs` is broadcast to the shape of `self`. /// + /// Assign can be used to overwrite uninitialized data in `self`, if the element + /// type is `Copy`. Only a few array methods will work correctly in this way. + /// /// **Panics** if broadcasting isn’t possible. pub fn assign(&mut self, rhs: &ArrayBase) where @@ -1916,16 +1919,31 @@ where A: Clone, S2: Data, { - self.zip_mut_with(rhs, |x, y| *x = y.clone()); + // guarantee validity even for uninited elements and A: Copy (conservative) because we + // traverse using raw pointer + Zip::from(self.raw_view_mut()).and_broadcast(rhs).apply(|x, y| + unsafe { + *x = y.clone(); + } + ); } /// Perform an elementwise assigment to `self` from element `x`. + /// + /// Fill can be used to overwrite uninitialized data in `self`, if the element + /// type is `Copy`. Only a few array methods will work correctly in this way. pub fn fill(&mut self, x: A) where S: DataMut, A: Clone, { - self.unordered_foreach_mut(move |elt| *elt = x.clone()); + // guarantee validity even for uninited elements and A: Copy (conservative) because we + // traverse using raw pointer + Zip::from(self.raw_view_mut()).apply(move |elt| + unsafe { + *elt = x.clone(); + } + ); } fn zip_mut_with_same_shape(&mut self, rhs: &ArrayBase, mut f: F)