From 7d6e140a91f7475270df274136bdff95b2436dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sylvain=20Monn=C3=A9?= Date: Tue, 28 Jul 2026 10:41:53 +0200 Subject: [PATCH 1/2] Implement new required Step methods forward/backward_overflowing --- CHANGELOG.md | 9 ++++++ src/common.rs | 12 +++++++ tests/tests.rs | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 832a637..460914d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## Unreleased + +### Fixed + +- Implemented `Step::forward_overflowing()` and `Step::backward_overflowing()`, which are new required + methods of the unstable `Step` trait ([rust#155114]). + +[rust#155114]: https://github.com/rust-lang/rust/pull/155114 + ## 2.1.1 ### Added diff --git a/src/common.rs b/src/common.rs index 994ebef..1d6352e 100644 --- a/src/common.rs +++ b/src/common.rs @@ -420,6 +420,18 @@ macro_rules! impl_step { None } } + + #[inline] + fn forward_overflowing(start: Self, count: usize) -> (Self, bool) { + let (res, overflow) = core::iter::Step::forward_overflowing(start.value, count); + (Self::masked_new(res), overflow || res > Self::MAX.value) + } + + #[inline] + fn backward_overflowing(start: Self, count: usize) -> (Self, bool) { + let (res, overflow) = core::iter::Step::backward_overflowing(start.value, count); + (Self::masked_new(res), overflow || res < Self::MIN.value) + } } }; } diff --git a/tests/tests.rs b/tests/tests.rs index ea1cf9b..0d3b9f5 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -3575,6 +3575,92 @@ fn backward_checked_signed() { assert_eq!(None, Step::backward_checked(i7::new(-64), 65)); } +#[cfg(feature = "step_trait")] +#[test] +fn forward_overflowing_unsigned() { + // In range + assert_eq!( + (u7::new(121), false), + Step::forward_overflowing(u7::new(120), 1) + ); + assert_eq!( + (u7::new(127), false), + Step::forward_overflowing(u7::new(120), 7) + ); + + // Out of range: the value is unspecified + assert!(Step::forward_overflowing(u7::new(120), 8).1); + + // Out of range for the underlying type + assert!(Step::forward_overflowing(u7::new(120), 140).1); +} + +#[cfg(feature = "step_trait")] +#[test] +fn forward_overflowing_signed() { + // In range + assert_eq!( + (i7::new(61), false), + Step::forward_overflowing(i7::new(60), 1) + ); + assert_eq!( + (i7::new(63), false), + Step::forward_overflowing(i7::new(56), 7) + ); + assert_eq!( + (i7::new(-60), false), + Step::forward_overflowing(i7::new(-64), 4) + ); + + // Out of range: the value is unspecified + assert!(Step::forward_overflowing(i7::new(60), 8).1); + + // Out of range for the underlying type + assert!(Step::forward_overflowing(i7::new(60), 140).1); +} + +#[cfg(feature = "step_trait")] +#[test] +fn backward_overflowing_unsigned() { + // In range + assert_eq!( + (u7::new(1), false), + Step::backward_overflowing(u7::new(10), 9) + ); + assert_eq!( + (u7::new(0), false), + Step::backward_overflowing(u7::new(10), 10) + ); + + // Out of range: the value is unspecified + assert!(Step::backward_overflowing(u7::new(10), 11).1); +} + +#[cfg(feature = "step_trait")] +#[test] +fn backward_overflowing_signed() { + // In range + assert_eq!( + (i7::new(1), false), + Step::backward_overflowing(i7::new(10), 9) + ); + assert_eq!( + (i7::new(-10), false), + Step::backward_overflowing(i7::new(10), 20) + ); + assert_eq!( + (i7::new(-64), false), + Step::backward_overflowing(i7::new(-60), 4) + ); + + // Out of range: the value is unspecified + assert!(Step::backward_overflowing(i7::new(-64), 1).1); + assert!(Step::backward_overflowing(i7::new(5), 70).1); + + // Out of range for the underlying type + assert!(Step::backward_overflowing(i7::new(0), 129).1); +} + #[cfg(feature = "step_trait")] #[test] fn steps_between_unsigned() { From 70fc6346bab80a5bae20846a9ad9fddce0826fbe Mon Sep 17 00:00:00 2001 From: Daniel Lehmann Date: Fri, 31 Jul 2026 01:23:51 -0700 Subject: [PATCH 2/2] Exclude nightly-only step_trait feature from semver check The new Step::forward_overflowing/backward_overflowing impls only exist on recent nightly, so the crate no longer compiles with step_trait on the stable toolchain cargo-semver-checks runs on. Semver-checking an unstable, nightly-gated feature has little value anyway. --- .github/workflows/check-semantic-versioning.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/check-semantic-versioning.yml b/.github/workflows/check-semantic-versioning.yml index 5b90bc2..9576aa9 100644 --- a/.github/workflows/check-semantic-versioning.yml +++ b/.github/workflows/check-semantic-versioning.yml @@ -14,5 +14,8 @@ jobs: # If we don't explicitly set which features to check `const_convert_and_const_trait_impl` will be used, # which fails on modern compilers (which cargo-semver-checks requires). # also, quickcheck was broken in 2.0.0, so we don't want that either. + # step_trait is excluded: it is nightly-only, and its `Step` impl tracks the + # current nightly `Step` trait, which doesn't compile on the stable toolchain + # this check runs on. feature-group: "only-explicit-features" - features: "std,step_trait,defmt,serde,borsh,schemars,arbitrary,num-traits" + features: "std,defmt,serde,borsh,schemars,arbitrary,num-traits"