Skip to content

Commit c7391e9

Browse files
authored
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
1 parent d5f32ec commit c7391e9

14 files changed

+39
-29
lines changed

.github/workflows/ci.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ name: Continuous integration
1010
env:
1111
CARGO_TERM_COLOR: always
1212
HOST: x86_64-unknown-linux-gnu
13-
FEATURES: "test docs"
13+
FEATURES: "approx,serde,rayon"
1414
RUSTFLAGS: "-D warnings"
1515
MSRV: 1.64.0
1616
BLAS_MSRV: 1.71.1
@@ -30,7 +30,7 @@ jobs:
3030
toolchain: ${{ matrix.rust }}
3131
components: clippy
3232
- uses: Swatinem/rust-cache@v2
33-
- run: cargo clippy --features docs
33+
- run: cargo clippy --features approx,serde,rayon
3434

3535
format:
3636
runs-on: ubuntu-latest
@@ -139,7 +139,7 @@ jobs:
139139
- uses: Swatinem/rust-cache@v2
140140
- name: Install cross
141141
run: cargo install cross
142-
- run: ./scripts/cross-tests.sh "docs" ${{ matrix.rust }} ${{ matrix.target }}
142+
- run: ./scripts/cross-tests.sh "approx,serde,rayon" ${{ matrix.rust }} ${{ matrix.target }}
143143

144144
cargo-careful:
145145
#if: ${{ github.event_name == 'merge_group' }}
@@ -161,10 +161,10 @@ jobs:
161161
strategy:
162162
matrix:
163163
rust:
164-
- stable
164+
- nightly # This is what docs.rs runs on, and is needed for the feature flags
165165
name: docs/${{ matrix.rust }}
166166
env:
167-
RUSTDOCFLAGS: "-Dwarnings"
167+
RUSTDOCFLAGS: "-Dwarnings --cfg docsrs"
168168
steps:
169169
- uses: actions/checkout@v4
170170
- uses: dtolnay/rust-toolchain@master

Cargo.toml

+4-9
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,6 @@ default = ["std"]
5959
blas = ["dep:cblas-sys", "dep:libc"]
6060

6161
serde = ["dep:serde"]
62-
# Old name for the serde feature
63-
serde-1 = ["dep:serde"]
64-
65-
# These features are used for testing
66-
test = []
67-
68-
# This feature is used for docs
69-
docs = ["approx", "serde", "rayon"]
7062

7163
std = ["num-traits/std", "matrixmultiply/std"]
7264
rayon = ["dep:rayon", "std"]
@@ -121,5 +113,8 @@ opt-level = 2
121113
no-dev-version = true
122114
tag-name = "{{version}}"
123115

116+
# Config specific to docs.rs
124117
[package.metadata.docs.rs]
125-
features = ["docs"]
118+
features = ["approx", "serde", "rayon"]
119+
# Define the configuration attribute `docsrs`
120+
rustdoc-args = ["--cfg", "docsrs"]

src/array_approx.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#[cfg(feature = "approx")]
2+
#[cfg_attr(docsrs, doc(cfg(feature = "approx")))]
23
mod approx_methods
34
{
45
use crate::imp_prelude::*;
@@ -10,8 +11,6 @@ mod approx_methods
1011
{
1112
/// A test for equality that uses the elementwise absolute difference to compute the
1213
/// approximate equality of two arrays.
13-
///
14-
/// **Requires crate feature `"approx"`**
1514
pub fn abs_diff_eq<S2>(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon) -> bool
1615
where
1716
A: ::approx::AbsDiffEq<S2::Elem>,
@@ -23,8 +22,6 @@ mod approx_methods
2322

2423
/// A test for equality that uses an elementwise relative comparison if the values are far
2524
/// apart; and the absolute difference otherwise.
26-
///
27-
/// **Requires crate feature `"approx"`**
2825
pub fn relative_eq<S2>(&self, other: &ArrayBase<S2, D>, epsilon: A::Epsilon, max_relative: A::Epsilon) -> bool
2926
where
3027
A: ::approx::RelativeEq<S2::Elem>,
@@ -192,4 +189,5 @@ macro_rules! impl_approx_traits {
192189
}
193190

194191
#[cfg(feature = "approx")]
192+
#[cfg_attr(docsrs, doc(cfg(feature = "approx")))]
195193
impl_approx_traits!(approx, "**Requires crate feature `\"approx\"`.**");

src/arraytraits.rs

+1
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ where
316316
}
317317

318318
#[cfg(feature = "serde")]
319+
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
319320
// Use version number so we can add a packed format later.
320321
pub const ARRAY_FORMAT_VERSION: u8 = 1u8;
321322

src/error.rs

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ impl PartialEq for ShapeError
8181
}
8282

8383
#[cfg(feature = "std")]
84+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
8485
impl Error for ShapeError {}
8586

8687
impl fmt::Display for ShapeError

src/impl_constructors.rs

+4
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ where S: DataOwned<Elem = A>
9999
/// assert!(array == arr1(&[0.0, 0.25, 0.5, 0.75, 1.0]))
100100
/// ```
101101
#[cfg(feature = "std")]
102+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
102103
pub fn linspace(start: A, end: A, n: usize) -> Self
103104
where A: Float
104105
{
@@ -117,6 +118,7 @@ where S: DataOwned<Elem = A>
117118
/// assert!(array == arr1(&[0., 1., 2., 3., 4.]))
118119
/// ```
119120
#[cfg(feature = "std")]
121+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
120122
pub fn range(start: A, end: A, step: A) -> Self
121123
where A: Float
122124
{
@@ -145,6 +147,7 @@ where S: DataOwned<Elem = A>
145147
/// # }
146148
/// ```
147149
#[cfg(feature = "std")]
150+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
148151
pub fn logspace(base: A, start: A, end: A, n: usize) -> Self
149152
where A: Float
150153
{
@@ -179,6 +182,7 @@ where S: DataOwned<Elem = A>
179182
/// # example().unwrap();
180183
/// ```
181184
#[cfg(feature = "std")]
185+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
182186
pub fn geomspace(start: A, end: A, n: usize) -> Option<Self>
183187
where A: Float
184188
{

src/impl_methods.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -2299,10 +2299,7 @@ where
22992299
let dim = dim.into_dimension();
23002300

23012301
// Note: zero strides are safe precisely because we return an read-only view
2302-
let broadcast_strides = match upcast(&dim, &self.dim, &self.strides) {
2303-
Some(st) => st,
2304-
None => return None,
2305-
};
2302+
let broadcast_strides = upcast(&dim, &self.dim, &self.strides)?;
23062303
unsafe { Some(ArrayView::new(self.ptr, dim, broadcast_strides)) }
23072304
}
23082305

src/iterators/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,7 @@ impl<A> DoubleEndedIterator for Baseiter<A, Ix1>
139139
#[inline]
140140
fn next_back(&mut self) -> Option<Self::Item>
141141
{
142-
let index = match self.index {
143-
None => return None,
144-
Some(ix) => ix,
145-
};
142+
let index = self.index?;
146143
self.dim[0] -= 1;
147144
let offset = Ix1::stride_offset(&self.dim, &self.strides);
148145
if index == self.dim {

src/lib.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#![doc(test(attr(allow(unused_variables))))]
2121
#![doc(test(attr(allow(deprecated))))]
2222
#![cfg_attr(not(feature = "std"), no_std)]
23+
// Enable the doc_cfg nightly feature for including feature gate flags in the documentation
24+
#![cfg_attr(docsrs, feature(doc_cfg))]
2325

2426
//! The `ndarray` crate provides an *n*-dimensional container for general elements
2527
//! and for numerics.
@@ -120,7 +122,7 @@ extern crate std;
120122
#[cfg(feature = "blas")]
121123
extern crate cblas_sys;
122124

123-
#[cfg(feature = "docs")]
125+
#[cfg(docsrs)]
124126
pub mod doc;
125127

126128
#[cfg(target_has_atomic = "ptr")]
@@ -148,6 +150,7 @@ use crate::iterators::{ElementsBase, ElementsBaseMut, Iter, IterMut};
148150
pub use crate::arraytraits::AsArray;
149151
pub use crate::linalg_traits::LinalgScalar;
150152
#[cfg(feature = "std")]
153+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
151154
pub use crate::linalg_traits::NdFloat;
152155

153156
pub use crate::stacking::{concatenate, stack};
@@ -189,9 +192,11 @@ mod layout;
189192
mod linalg_traits;
190193
mod linspace;
191194
#[cfg(feature = "std")]
195+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
192196
pub use crate::linspace::{linspace, range, Linspace};
193197
mod logspace;
194198
#[cfg(feature = "std")]
199+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
195200
pub use crate::logspace::{logspace, Logspace};
196201
mod math_cell;
197202
mod numeric_util;
@@ -1587,6 +1592,7 @@ where
15871592

15881593
// parallel methods
15891594
#[cfg(feature = "rayon")]
1595+
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
15901596
pub mod parallel;
15911597

15921598
mod impl_1d;

src/linalg_traits.rs

+5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ impl<T> LinalgScalar for T where T: 'static + Copy + Zero + One + Add<Output = T
3939
/// operations (`ScalarOperand`).
4040
///
4141
/// This trait can only be implemented by `f32` and `f64`.
42+
///
43+
/// **Requires default crate feature `"std"`**
4244
#[cfg(feature = "std")]
45+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4346
pub trait NdFloat:
4447
Float
4548
+ AddAssign
@@ -59,6 +62,8 @@ pub trait NdFloat:
5962
}
6063

6164
#[cfg(feature = "std")]
65+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
6266
impl NdFloat for f32 {}
6367
#[cfg(feature = "std")]
68+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
6469
impl NdFloat for f64 {}

src/numeric/impl_float_maths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ macro_rules! binary_ops {
5454
///
5555
/// Element-wise math functions for any array type that contains float number.
5656
#[cfg(feature = "std")]
57+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
5758
impl<A, S, D> ArrayBase<S, D>
5859
where
5960
A: 'static + Float,

src/numeric/impl_numeric.rs

+4
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ where
140140
/// ```
141141
#[track_caller]
142142
#[cfg(feature = "std")]
143+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
143144
pub fn var(&self, ddof: A) -> A
144145
where A: Float + FromPrimitive
145146
{
@@ -205,6 +206,7 @@ where
205206
/// ```
206207
#[track_caller]
207208
#[cfg(feature = "std")]
209+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
208210
pub fn std(&self, ddof: A) -> A
209211
where A: Float + FromPrimitive
210212
{
@@ -361,6 +363,7 @@ where
361363
/// ```
362364
#[track_caller]
363365
#[cfg(feature = "std")]
366+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
364367
pub fn var_axis(&self, axis: Axis, ddof: A) -> Array<A, D::Smaller>
365368
where
366369
A: Float + FromPrimitive,
@@ -431,6 +434,7 @@ where
431434
/// ```
432435
#[track_caller]
433436
#[cfg(feature = "std")]
437+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
434438
pub fn std_axis(&self, axis: Axis, ddof: A) -> Array<A, D::Smaller>
435439
where
436440
A: Float + FromPrimitive,

src/parallel/impl_par_methods.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use crate::parallel::prelude::*;
88
use crate::partial::Partial;
99

1010
/// # Parallel methods
11-
///
12-
/// These methods require crate feature `rayon`.
1311
impl<A, S, D> ArrayBase<S, D>
1412
where
1513
S: DataMut<Elem = A>,

src/partial.rs

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ impl<T> Partial<T>
3737
}
3838

3939
#[cfg(feature = "rayon")]
40+
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
4041
pub(crate) fn stub() -> Self
4142
{
4243
Self {
@@ -46,6 +47,7 @@ impl<T> Partial<T>
4647
}
4748

4849
#[cfg(feature = "rayon")]
50+
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
4951
pub(crate) fn is_stub(&self) -> bool
5052
{
5153
self.ptr.is_null()
@@ -60,6 +62,7 @@ impl<T> Partial<T>
6062
}
6163

6264
#[cfg(feature = "rayon")]
65+
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
6366
/// Merge if they are in order (left to right) and contiguous.
6467
/// Skips merge if T does not need drop.
6568
pub(crate) fn try_merge(mut left: Self, right: Self) -> Self

0 commit comments

Comments
 (0)