From c7391e99073b40daef5de0563cbcc32aea0facb0 Mon Sep 17 00:00:00 2001 From: akern40 Date: Sun, 2 Feb 2025 23:54:45 -0500 Subject: [PATCH] Simplify features and make documentation call out feature gates (#1479) * Makes use of the nightly `doc_cfg` feature to automatically mark feature-gated items as requiring that feature. This is possible thanks to the fact that docs.rs runs on nightly. While this may not be stabilized (and therefore may eventually reverse), I think it's extremely useful to users and only requires small additional configurations that would be easy to remove in the future. * Adds appropriate arguments to CI/CD and removes serde-1, test, and docs features * Fixes clippy complaining about `return None` instead of question marks --- .github/workflows/ci.yaml | 10 +++++----- Cargo.toml | 13 ++++--------- src/array_approx.rs | 6 ++---- src/arraytraits.rs | 1 + src/error.rs | 1 + src/impl_constructors.rs | 4 ++++ src/impl_methods.rs | 5 +---- src/iterators/mod.rs | 5 +---- src/lib.rs | 8 +++++++- src/linalg_traits.rs | 5 +++++ src/numeric/impl_float_maths.rs | 1 + src/numeric/impl_numeric.rs | 4 ++++ src/parallel/impl_par_methods.rs | 2 -- src/partial.rs | 3 +++ 14 files changed, 39 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ae74aeb45..1a1ee6415 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ name: Continuous integration env: CARGO_TERM_COLOR: always HOST: x86_64-unknown-linux-gnu - FEATURES: "test docs" + FEATURES: "approx,serde,rayon" RUSTFLAGS: "-D warnings" MSRV: 1.64.0 BLAS_MSRV: 1.71.1 @@ -30,7 +30,7 @@ jobs: toolchain: ${{ matrix.rust }} components: clippy - uses: Swatinem/rust-cache@v2 - - run: cargo clippy --features docs + - run: cargo clippy --features approx,serde,rayon format: runs-on: ubuntu-latest @@ -139,7 +139,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Install cross run: cargo install cross - - run: ./scripts/cross-tests.sh "docs" ${{ matrix.rust }} ${{ matrix.target }} + - run: ./scripts/cross-tests.sh "approx,serde,rayon" ${{ matrix.rust }} ${{ matrix.target }} cargo-careful: #if: ${{ github.event_name == 'merge_group' }} @@ -161,10 +161,10 @@ jobs: strategy: matrix: rust: - - stable + - nightly # This is what docs.rs runs on, and is needed for the feature flags name: docs/${{ matrix.rust }} env: - RUSTDOCFLAGS: "-Dwarnings" + RUSTDOCFLAGS: "-Dwarnings --cfg docsrs" steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master diff --git a/Cargo.toml b/Cargo.toml index 5c7217025..3d1c1dde6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,14 +59,6 @@ default = ["std"] blas = ["dep:cblas-sys", "dep:libc"] serde = ["dep:serde"] -# Old name for the serde feature -serde-1 = ["dep:serde"] - -# These features are used for testing -test = [] - -# This feature is used for docs -docs = ["approx", "serde", "rayon"] std = ["num-traits/std", "matrixmultiply/std"] rayon = ["dep:rayon", "std"] @@ -121,5 +113,8 @@ opt-level = 2 no-dev-version = true tag-name = "{{version}}" +# Config specific to docs.rs [package.metadata.docs.rs] -features = ["docs"] +features = ["approx", "serde", "rayon"] +# Define the configuration attribute `docsrs` +rustdoc-args = ["--cfg", "docsrs"] diff --git a/src/array_approx.rs b/src/array_approx.rs index 493864c7e..c6fd174d1 100644 --- a/src/array_approx.rs +++ b/src/array_approx.rs @@ -1,4 +1,5 @@ #[cfg(feature = "approx")] +#[cfg_attr(docsrs, doc(cfg(feature = "approx")))] mod approx_methods { use crate::imp_prelude::*; @@ -10,8 +11,6 @@ mod approx_methods { /// A test for equality that uses the elementwise absolute difference to compute the /// approximate equality of two arrays. - /// - /// **Requires crate feature `"approx"`** pub fn abs_diff_eq(&self, other: &ArrayBase, epsilon: A::Epsilon) -> bool where A: ::approx::AbsDiffEq, @@ -23,8 +22,6 @@ mod approx_methods /// A test for equality that uses an elementwise relative comparison if the values are far /// apart; and the absolute difference otherwise. - /// - /// **Requires crate feature `"approx"`** pub fn relative_eq(&self, other: &ArrayBase, epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool where A: ::approx::RelativeEq, @@ -192,4 +189,5 @@ macro_rules! impl_approx_traits { } #[cfg(feature = "approx")] +#[cfg_attr(docsrs, doc(cfg(feature = "approx")))] impl_approx_traits!(approx, "**Requires crate feature `\"approx\"`.**"); diff --git a/src/arraytraits.rs b/src/arraytraits.rs index d7a00fcfe..62f95df4a 100644 --- a/src/arraytraits.rs +++ b/src/arraytraits.rs @@ -316,6 +316,7 @@ where } #[cfg(feature = "serde")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde")))] // Use version number so we can add a packed format later. pub const ARRAY_FORMAT_VERSION: u8 = 1u8; diff --git a/src/error.rs b/src/error.rs index eb7395ad8..e19c32075 100644 --- a/src/error.rs +++ b/src/error.rs @@ -81,6 +81,7 @@ impl PartialEq for ShapeError } #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] impl Error for ShapeError {} impl fmt::Display for ShapeError diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index 260937a90..c1e5b1b8b 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -99,6 +99,7 @@ where S: DataOwned /// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0])) /// ``` #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn linspace(start: A, end: A, n: usize) -> Self where A: Float { @@ -117,6 +118,7 @@ where S: DataOwned /// assert!(array == arr1(&[0., 1., 2., 3., 4.])) /// ``` #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn range(start: A, end: A, step: A) -> Self where A: Float { @@ -145,6 +147,7 @@ where S: DataOwned /// # } /// ``` #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn logspace(base: A, start: A, end: A, n: usize) -> Self where A: Float { @@ -179,6 +182,7 @@ where S: DataOwned /// # example().unwrap(); /// ``` #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn geomspace(start: A, end: A, n: usize) -> Option where A: Float { diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 4a00ea000..3da63b936 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -2299,10 +2299,7 @@ where let dim = dim.into_dimension(); // Note: zero strides are safe precisely because we return an read-only view - let broadcast_strides = match upcast(&dim, &self.dim, &self.strides) { - Some(st) => st, - None => return None, - }; + let broadcast_strides = upcast(&dim, &self.dim, &self.strides)?; unsafe { Some(ArrayView::new(self.ptr, dim, broadcast_strides)) } } diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 01fff14f5..e0da8f6c9 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -139,10 +139,7 @@ impl DoubleEndedIterator for Baseiter #[inline] fn next_back(&mut self) -> Option { - let index = match self.index { - None => return None, - Some(ix) => ix, - }; + let index = self.index?; self.dim[0] -= 1; let offset = Ix1::stride_offset(&self.dim, &self.strides); if index == self.dim { diff --git a/src/lib.rs b/src/lib.rs index b163f16a5..f0b64028f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,8 @@ #![doc(test(attr(allow(unused_variables))))] #![doc(test(attr(allow(deprecated))))] #![cfg_attr(not(feature = "std"), no_std)] +// Enable the doc_cfg nightly feature for including feature gate flags in the documentation +#![cfg_attr(docsrs, feature(doc_cfg))] //! The `ndarray` crate provides an *n*-dimensional container for general elements //! and for numerics. @@ -120,7 +122,7 @@ extern crate std; #[cfg(feature = "blas")] extern crate cblas_sys; -#[cfg(feature = "docs")] +#[cfg(docsrs)] pub mod doc; #[cfg(target_has_atomic = "ptr")] @@ -148,6 +150,7 @@ use crate::iterators::{ElementsBase, ElementsBaseMut, Iter, IterMut}; pub use crate::arraytraits::AsArray; pub use crate::linalg_traits::LinalgScalar; #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub use crate::linalg_traits::NdFloat; pub use crate::stacking::{concatenate, stack}; @@ -189,9 +192,11 @@ mod layout; mod linalg_traits; mod linspace; #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub use crate::linspace::{linspace, range, Linspace}; mod logspace; #[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub use crate::logspace::{logspace, Logspace}; mod math_cell; mod numeric_util; @@ -1587,6 +1592,7 @@ where // parallel methods #[cfg(feature = "rayon")] +#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] pub mod parallel; mod impl_1d; diff --git a/src/linalg_traits.rs b/src/linalg_traits.rs index 65d264c40..ec1aebbe7 100644 --- a/src/linalg_traits.rs +++ b/src/linalg_traits.rs @@ -39,7 +39,10 @@ impl LinalgScalar for T where T: 'static + Copy + Zero + One + Add ArrayBase where A: 'static + Float, diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index 6c67b9135..a8a008395 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -140,6 +140,7 @@ where /// ``` #[track_caller] #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn var(&self, ddof: A) -> A where A: Float + FromPrimitive { @@ -205,6 +206,7 @@ where /// ``` #[track_caller] #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn std(&self, ddof: A) -> A where A: Float + FromPrimitive { @@ -361,6 +363,7 @@ where /// ``` #[track_caller] #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn var_axis(&self, axis: Axis, ddof: A) -> Array where A: Float + FromPrimitive, @@ -431,6 +434,7 @@ where /// ``` #[track_caller] #[cfg(feature = "std")] + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] pub fn std_axis(&self, axis: Axis, ddof: A) -> Array where A: Float + FromPrimitive, diff --git a/src/parallel/impl_par_methods.rs b/src/parallel/impl_par_methods.rs index c6af4e8f3..7f01ea32f 100644 --- a/src/parallel/impl_par_methods.rs +++ b/src/parallel/impl_par_methods.rs @@ -8,8 +8,6 @@ use crate::parallel::prelude::*; use crate::partial::Partial; /// # Parallel methods -/// -/// These methods require crate feature `rayon`. impl ArrayBase where S: DataMut, diff --git a/src/partial.rs b/src/partial.rs index 99aba75a8..4509e77dc 100644 --- a/src/partial.rs +++ b/src/partial.rs @@ -37,6 +37,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] pub(crate) fn stub() -> Self { Self { @@ -46,6 +47,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] pub(crate) fn is_stub(&self) -> bool { self.ptr.is_null() @@ -60,6 +62,7 @@ impl Partial } #[cfg(feature = "rayon")] + #[cfg_attr(docsrs, doc(cfg(feature = "rayon")))] /// Merge if they are in order (left to right) and contiguous. /// Skips merge if T does not need drop. pub(crate) fn try_merge(mut left: Self, right: Self) -> Self