From eedb860565dcc428e9cb523e4caa85d2f7f3af0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Tue, 3 Aug 2021 17:26:56 +0200 Subject: [PATCH] Fix missing docs. --- CHANGELOG.md | 2 +- src/base/array_storage.rs | 9 ++++--- src/base/blas_uninit.rs | 54 +++++++++------------------------------ src/base/construction.rs | 1 + src/base/matrix.rs | 1 + src/base/mod.rs | 1 + src/base/storage.rs | 9 +++++++ src/base/uninit.rs | 29 +++++++++++++++++++-- src/lib.rs | 2 +- 9 files changed, 59 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5af293ab..8eae0834 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). -## [0.29.0] +## [0.29.0] - WIP ### Modified - The closure given to `apply`, `zip_apply`, `zip_zip_apply` must now modify the first argument inplace, instead of returning a new value. This makes these diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 5ed97f46..7b2bb799 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -22,7 +22,7 @@ use crate::base::dimension::{Const, ToTypenum}; use crate::base::storage::{IsContiguous, Owned, RawStorage, RawStorageMut, ReshapableStorage}; use crate::base::Scalar; use crate::Storage; -use std::mem::{self, MaybeUninit}; +use std::mem; /* * @@ -35,12 +35,14 @@ use std::mem::{self, MaybeUninit}; pub struct ArrayStorage(pub [[T; R]; C]); impl ArrayStorage { + /// Converts this array storage to a slice. #[inline] pub fn as_slice(&self) -> &[T] { // SAFETY: this is OK because ArrayStorage is contiguous. unsafe { self.as_slice_unchecked() } } + /// Converts this array storage to a mutable slice. #[inline] pub fn as_mut_slice(&mut self) -> &mut [T] { // SAFETY: this is OK because ArrayStorage is contiguous. @@ -237,14 +239,15 @@ where where V: SeqAccess<'a>, { - let mut out: ArrayStorage, R, C> = + let mut out: ArrayStorage, R, C> = DefaultAllocator::allocate_uninit(Const::, Const::); let mut curr = 0; while let Some(value) = visitor.next_element()? { *out.as_mut_slice() .get_mut(curr) - .ok_or_else(|| V::Error::invalid_length(curr, &self))? = MaybeUninit::new(value); + .ok_or_else(|| V::Error::invalid_length(curr, &self))? = + core::mem::MaybeUninit::new(value); curr += 1; } diff --git a/src/base/blas_uninit.rs b/src/base/blas_uninit.rs index 2b3c5fc3..04812d7e 100644 --- a/src/base/blas_uninit.rs +++ b/src/base/blas_uninit.rs @@ -73,19 +73,12 @@ fn array_axc( } } -/// Computes `self = a * x * c + b * self`. +/// Computes `y = a * x * c + b * y`. /// -/// If `b` is zero, `self` is never read from. +/// If `b` is zero, `y` is never read from and may be uninitialized. /// -/// # Examples: -/// -/// ``` -/// # use nalgebra::Vector3; -/// let mut vec1 = Vector3::new(1.0, 2.0, 3.0); -/// let vec2 = Vector3::new(0.1, 0.2, 0.3); -/// vec1.axcpy(5.0, &vec2, 2.0, 5.0); -/// assert_eq!(vec1, Vector3::new(6.0, 12.0, 18.0)); -/// ``` +/// # Safety +/// This is UB if `Status == Uninit && b != 0`. #[inline] #[allow(clippy::many_single_char_names)] pub unsafe fn axcpy_uninit( @@ -119,22 +112,13 @@ pub unsafe fn axcpy_uninit( } } -/// Computes `self = alpha * a * x + beta * self`, where `a` is a matrix, `x` a vector, and +/// Computes `y = alpha * a * x + beta * y`, where `a` is a matrix, `x` a vector, and /// `alpha, beta` two scalars. /// -/// If `beta` is zero, `self` is never read. +/// If `beta` is zero, `y` is never read from and may be uninitialized. /// -/// # Examples: -/// -/// ``` -/// # use nalgebra::{Matrix2, Vector2}; -/// let mut vec1 = Vector2::new(1.0, 2.0); -/// let vec2 = Vector2::new(0.1, 0.2); -/// let mat = Matrix2::new(1.0, 2.0, -/// 3.0, 4.0); -/// vec1.gemv(10.0, &mat, &vec2, 5.0); -/// assert_eq!(vec1, Vector2::new(10.0, 21.0)); -/// ``` +/// # Safety +/// This is UB if `Status == Uninit && beta != 0`. #[inline] pub unsafe fn gemv_uninit( status: Status, @@ -193,27 +177,13 @@ pub unsafe fn gemv_uninit UninitMatrix where DefaultAllocator: Allocator, { + /// Builds a matrix with uninitialized elements of type `MaybeUninit`. pub fn uninit(nrows: R, ncols: C) -> Self { // SAFETY: this is OK because the dimension automatically match the storage // because we are building an owned storage. diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 6e868354..392ea343 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -451,6 +451,7 @@ impl> Matrix { (nrows.value(), ncols.value()) } + /// The shape of this matrix wrapped into their representative types (`Const` or `Dynamic`). #[inline] #[must_use] pub fn shape_generic(&self) -> (R, C) { diff --git a/src/base/mod.rs b/src/base/mod.rs index 88b79dc3..c6279ba3 100644 --- a/src/base/mod.rs +++ b/src/base/mod.rs @@ -38,6 +38,7 @@ mod blas_uninit; pub mod helper; mod interpolation; mod min_max; +/// Mechanisms for working with values that may not be initialized. pub mod uninit; pub use self::matrix::*; diff --git a/src/base/storage.rs b/src/base/storage.rs index 7ef7e152..76a60ce3 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -32,6 +32,9 @@ pub type CStride = /// The trait shared by all matrix data storage. /// /// TODO: doc +/// In generic code, it is recommended use the `Storage` trait bound instead. The `RawStorage` +/// trait bound is generally used by code that needs to work with storages that contains +/// `MaybeUninit` elements. /// /// Note that `Self` must always have a number of elements compatible with the matrix length (given /// by `R` and `C` if they are known at compile-time). For example, implementors of this trait @@ -125,6 +128,7 @@ pub unsafe trait RawStorage: Sized { unsafe fn as_slice_unchecked(&self) -> &[T]; } +/// Trait shared by all matrix data storage that don’t contain any uninitialized elements. pub unsafe trait Storage: RawStorage { /// Builds a matrix data storage that does not contain any reference. fn into_owned(self) -> Owned @@ -139,6 +143,10 @@ pub unsafe trait Storage: RawStorage { /// Trait implemented by matrix data storage that can provide a mutable access to its elements. /// +/// In generic code, it is recommended use the `StorageMut` trait bound instead. The +/// `RawStorageMut` trait bound is generally used by code that needs to work with storages that +/// contains `MaybeUninit` elements. +/// /// Note that a mutable access does not mean that the matrix owns its data. For example, a mutable /// matrix slice can provide mutable access to its elements even if it does not own its data (it /// contains only an internal reference to them). @@ -217,6 +225,7 @@ pub unsafe trait RawStorageMut: RawStorage { unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T]; } +/// Trait shared by all mutable matrix data storage that don’t contain any uninitialized elements. pub unsafe trait StorageMut: Storage + RawStorageMut { diff --git a/src/base/uninit.rs b/src/base/uninit.rs index 7fc5f84e..5d37a249 100644 --- a/src/base/uninit.rs +++ b/src/base/uninit.rs @@ -1,19 +1,44 @@ use std::mem::MaybeUninit; -// # Safety -// This trait must not be implemented outside of this crate. +/// This trait is used to write code that may work on matrices that may or may not +/// be initialized. +/// +/// This trait is used to describe how a value must be accessed to initialize it or +/// to retrieve a reference or mutable reference. Typically, a function accepting +/// both initialized and uninitialized inputs should have a `Status: InitStatus` +/// type parameter. Then the methods of the `Status` can be used to access the element. +/// +/// # Safety +/// This trait must not be implemented outside of this crate. pub unsafe trait InitStatus: Copy { + /// The type of the values with the initialization status described by `Self`. type Value; + + /// Initialize the given element. fn init(out: &mut Self::Value, t: T); + + /// Retrieve a reference to the element, assuming that it is initialized. + /// + /// # Safety + /// This is unsound if the referenced value isn’t initialized. unsafe fn assume_init_ref(t: &Self::Value) -> &T; + + /// Retrieve a mutable reference to the element, assuming that it is initialized. + /// + /// # Safety + /// This is unsound if the referenced value isn’t initialized. unsafe fn assume_init_mut(t: &mut Self::Value) -> &mut T; } #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// A type implementing `InitStatus` indicating that the value is completely initialized. pub struct Init; #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// A type implementing `InitStatus` indicating that the value is completely unitialized. pub struct Uninit; #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// A type implementing `InitStatus` indicating that the value is initialized even if the value +/// has the type `MaybeUninit` (i.e. when `Status == Uninit`). pub struct Initialized(pub Status); unsafe impl InitStatus for Init { diff --git a/src/lib.rs b/src/lib.rs index aa8fcdf0..5fc38070 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ an optimized set of tools for computer graphics and physics. Those features incl #![allow(unused_variables, unused_mut)] #![deny( + missing_docs, nonstandard_style, unused_parens, unused_qualifications, @@ -82,7 +83,6 @@ an optimized set of tools for computer graphics and physics. Those features incl future_incompatible, missing_copy_implementations )] -// #![deny(missing_docs)] // XXX: deny that #![doc( html_favicon_url = "https://nalgebra.org/img/favicon.ico", html_root_url = "https://docs.rs/nalgebra/0.25.0"