Skip to content

Commit 287ce4c

Browse files
committed
Remove ExactSizeIterator impls for RangeInclusive<{i16,u16}>
They are incorrect on 16-bit platforms since the return value of `len()` might overflow `usize`. Impls for `Range<u32>` and `Range<i32>` are similarly incorrect, but were stabilized in Rust 1.0.0 so removing them would be a breaking change. `(0..66_000_u32).len()` for example will compile without error or warnings on 16-bit platforms, but panic at run-time.
1 parent b270e7f commit 287ce4c

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

src/libcore/iter/range.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,34 @@ impl<A: Step> Iterator for ops::Range<A> {
305305
}
306306

307307
// These macros generate `ExactSizeIterator` impls for various range types.
308-
// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded
309-
// because they cannot guarantee having a length <= usize::MAX, which is
310-
// required by ExactSizeIterator.
311-
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
312-
range_incl_exact_iter_impl!(u8 u16 i8 i16);
308+
//
309+
// * `ExactSizeIterator::len` is required to always return an exact `usize`,
310+
// so no range can be longer than usize::MAX.
311+
// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`.
312+
// For integer types in `RangeInclusive<_>`
313+
// this is the case for types *strictly narrower* than `usize`
314+
// since e.g. `(0...u64::MAX).len()` would be `u64::MAX + 1`.
315+
// * It hurts portability to have APIs (including `impl`s) that are only available on some platforms,
316+
// so only `impl`s that are always valid should exist, regardless of the current target platform.
317+
// (NOTE: https://github.com/rust-lang/rust/issues/41619 might change this.)
318+
// * Support exists in-tree for MSP430: https://forge.rust-lang.org/platform-support.html#tier-3
319+
// and out-of-tree for AVR: https://github.com/avr-rust/rust
320+
// Both are platforms where `usize` is 16 bits wide.
321+
range_exact_iter_impl! {
322+
usize u8 u16
323+
isize i8 i16
324+
325+
// These are incorrect per the reasoning above,
326+
// but removing them would be a breaking change as they were stabilized in Rust 1.0.0.
327+
// So `(0..66_000_u32).len()` for example will compile without error or warnings
328+
// on 16-bit platforms, but panic at run-time.
329+
u32
330+
i32
331+
}
332+
range_incl_exact_iter_impl! {
333+
u8
334+
i8
335+
}
313336

314337
// These macros generate `TrustedLen` impls.
315338
//

0 commit comments

Comments
 (0)