Skip to content

Commit 85c975b

Browse files
authored
Rollup merge of rust-lang#60542 - timvermeulen:step_sub_usize, r=scottmcm
Add Step::sub_usize Required for rust-lang#54054. I'm aware that the `Step` trait needs a rework, but this still seems like a reasonable addition? This currently doesn't compile because Chalk contains a type that implement this trait, and this is a breaking change. How can that be fixed?
2 parents 8e3f003 + f1d0829 commit 85c975b

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

src/libcore/iter/range.rs

+35
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized {
3434

3535
/// Adds a `usize`, returning `None` on overflow.
3636
fn add_usize(&self, n: usize) -> Option<Self>;
37+
38+
/// Subtracts a `usize`, returning `None` on underflow.
39+
fn sub_usize(&self, n: usize) -> Option<Self> {
40+
// this default implementation makes the addition of `sub_usize` a non-breaking change
41+
let _ = n;
42+
unimplemented!()
43+
}
3744
}
3845

3946
// These are still macro-generated because the integer literals resolve to different types.
@@ -85,6 +92,15 @@ macro_rules! step_impl_unsigned {
8592
}
8693
}
8794

95+
#[inline]
96+
#[allow(unreachable_patterns)]
97+
fn sub_usize(&self, n: usize) -> Option<Self> {
98+
match <$t>::try_from(n) {
99+
Ok(n_as_t) => self.checked_sub(n_as_t),
100+
Err(_) => None,
101+
}
102+
}
103+
88104
step_identical_methods!();
89105
}
90106
)*)
@@ -125,6 +141,25 @@ macro_rules! step_impl_signed {
125141
}
126142
}
127143

144+
#[inline]
145+
#[allow(unreachable_patterns)]
146+
fn sub_usize(&self, n: usize) -> Option<Self> {
147+
match <$unsigned>::try_from(n) {
148+
Ok(n_as_unsigned) => {
149+
// Wrapping in unsigned space handles cases like
150+
// `80_i8.sub_usize(200) == Some(-120_i8)`,
151+
// even though 200_usize is out of range for i8.
152+
let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t;
153+
if wrapped <= *self {
154+
Some(wrapped)
155+
} else {
156+
None // Subtraction underflowed
157+
}
158+
}
159+
Err(_) => None,
160+
}
161+
}
162+
128163
step_identical_methods!();
129164
}
130165
)*)

src/librustc_data_structures/indexed_vec.rs

+5
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,11 @@ macro_rules! newtype_index {
212212
fn add_usize(&self, u: usize) -> Option<Self> {
213213
Idx::index(*self).checked_add(u).map(Self::new)
214214
}
215+
216+
#[inline]
217+
fn sub_usize(&self, u: usize) -> Option<Self> {
218+
Idx::index(*self).checked_sub(u).map(Self::new)
219+
}
215220
}
216221

217222
impl From<$type> for u32 {

src/test/run-pass/impl-trait/example-calendar.rs

+4
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ impl std::iter::Step for NaiveDate {
180180
fn add_usize(&self, _: usize) -> Option<Self> {
181181
unimplemented!()
182182
}
183+
184+
fn sub_usize(&self, _: usize) -> Option<Self> {
185+
unimplemented!()
186+
}
183187
}
184188

185189
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]

0 commit comments

Comments
 (0)