diff options
| author | Tim Vermeulen <tvermeulen@me.com> | 2019-05-04 12:04:52 +0200 |
|---|---|---|
| committer | Tim Vermeulen <tvermeulen@me.com> | 2019-05-25 02:53:08 +0200 |
| commit | f1d0829e20e3ff3ff78a09136968612887544af2 (patch) | |
| tree | c64d009d967eb8f6ab530d07d4836f5e3382bd7f | |
| parent | dec4c5201f88efbc3020b04ba96a5ee2c3b6cfcd (diff) | |
| download | rust-f1d0829e20e3ff3ff78a09136968612887544af2.tar.gz rust-f1d0829e20e3ff3ff78a09136968612887544af2.zip | |
Add Step::sub_usize
| -rw-r--r-- | src/libcore/iter/range.rs | 35 | ||||
| -rw-r--r-- | src/librustc_data_structures/indexed_vec.rs | 5 | ||||
| -rw-r--r-- | src/test/run-pass/impl-trait/example-calendar.rs | 4 |
3 files changed, 44 insertions, 0 deletions
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index f8a975cc8d4..6bbf776fb8f 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized { /// Adds a `usize`, returning `None` on overflow. fn add_usize(&self, n: usize) -> Option<Self>; + + /// Subtracts a `usize`, returning `None` on underflow. + fn sub_usize(&self, n: usize) -> Option<Self> { + // this default implementation makes the addition of `sub_usize` a non-breaking change + let _ = n; + unimplemented!() + } } // These are still macro-generated because the integer literals resolve to different types. @@ -85,6 +92,15 @@ macro_rules! step_impl_unsigned { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option<Self> { + match <$t>::try_from(n) { + Ok(n_as_t) => self.checked_sub(n_as_t), + Err(_) => None, + } + } + step_identical_methods!(); } )*) @@ -125,6 +141,25 @@ macro_rules! step_impl_signed { } } + #[inline] + #[allow(unreachable_patterns)] + fn sub_usize(&self, n: usize) -> Option<Self> { + match <$unsigned>::try_from(n) { + Ok(n_as_unsigned) => { + // Wrapping in unsigned space handles cases like + // `80_i8.sub_usize(200) == Some(-120_i8)`, + // even though 200_usize is out of range for i8. + let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t; + if wrapped <= *self { + Some(wrapped) + } else { + None // Subtraction underflowed + } + } + Err(_) => None, + } + } + step_identical_methods!(); } )*) diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 359b89f683d..c7f6e54c3d5 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -212,6 +212,11 @@ macro_rules! newtype_index { fn add_usize(&self, u: usize) -> Option<Self> { Idx::index(*self).checked_add(u).map(Self::new) } + + #[inline] + fn sub_usize(&self, u: usize) -> Option<Self> { + Idx::index(*self).checked_sub(u).map(Self::new) + } } impl From<$type> for u32 { diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index 968e9b7d34a..f1b1656745e 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -180,6 +180,10 @@ impl std::iter::Step for NaiveDate { fn add_usize(&self, _: usize) -> Option<Self> { unimplemented!() } + + fn sub_usize(&self, _: usize) -> Option<Self> { + unimplemented!() + } } #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] |
