diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 793cbf994956f..24f955a70b67e 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -10,6 +10,7 @@ use crate::intrinsics::{assume, exact_div, unchecked_sub}; use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess}; use crate::marker::{PhantomData, Send, Sized, Sync}; use crate::mem; +use crate::num::NonZeroUsize; use crate::ptr::NonNull; use super::{from_raw_parts, from_raw_parts_mut}; @@ -1187,12 +1188,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] } #[stable(feature = "rust1", since = "1.0.0")] pub struct Windows<'a, T: 'a> { v: &'a [T], - size: usize, + size: NonZeroUsize, } impl<'a, T: 'a> Windows<'a, T> { #[inline] - pub(super) fn new(slice: &'a [T], size: usize) -> Self { + pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self { Self { v: slice, size } } } @@ -1211,10 +1212,10 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn next(&mut self) -> Option<&'a [T]> { - if self.size > self.v.len() { + if self.size.get() > self.v.len() { None } else { - let ret = Some(&self.v[..self.size]); + let ret = Some(&self.v[..self.size.get()]); self.v = &self.v[1..]; ret } @@ -1222,10 +1223,10 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn size_hint(&self) -> (usize, Option) { - if self.size > self.v.len() { + if self.size.get() > self.v.len() { (0, Some(0)) } else { - let size = self.v.len() - self.size + 1; + let size = self.v.len() - self.size.get() + 1; (size, Some(size)) } } @@ -1237,7 +1238,7 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn nth(&mut self, n: usize) -> Option { - let (end, overflow) = self.size.overflowing_add(n); + let (end, overflow) = self.size.get().overflowing_add(n); if end > self.v.len() || overflow { self.v = &[]; None @@ -1250,10 +1251,10 @@ impl<'a, T> Iterator for Windows<'a, T> { #[inline] fn last(self) -> Option { - if self.size > self.v.len() { + if self.size.get() > self.v.len() { None } else { - let start = self.v.len() - self.size; + let start = self.v.len() - self.size.get(); Some(&self.v[start..]) } } @@ -1264,7 +1265,7 @@ impl<'a, T> Iterator for Windows<'a, T> { // which means that `i` cannot overflow an `isize`, and the // slice created by `from_raw_parts` is a subslice of `self.v` // thus is guaranteed to be valid for the lifetime `'a` of `self.v`. - unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) } + unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size.get()) } } } @@ -1272,10 +1273,10 @@ impl<'a, T> Iterator for Windows<'a, T> { impl<'a, T> DoubleEndedIterator for Windows<'a, T> { #[inline] fn next_back(&mut self) -> Option<&'a [T]> { - if self.size > self.v.len() { + if self.size.get() > self.v.len() { None } else { - let ret = Some(&self.v[self.v.len() - self.size..]); + let ret = Some(&self.v[self.v.len() - self.size.get()..]); self.v = &self.v[..self.v.len() - 1]; ret } @@ -1284,11 +1285,11 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { #[inline] fn nth_back(&mut self, n: usize) -> Option { let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.size || overflow { + if end < self.size.get() || overflow { self.v = &[]; None } else { - let ret = &self.v[end - self.size..end]; + let ret = &self.v[end - self.size.get()..end]; self.v = &self.v[..end - 1]; Some(ret) } diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 9373c6feccda3..73d085c3fb299 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -11,6 +11,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::marker::Copy; use crate::mem; +use crate::num::NonZeroUsize; use crate::ops::{FnMut, Range, RangeBounds}; use crate::option::Option; use crate::option::Option::{None, Some}; @@ -751,7 +752,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn windows(&self, size: usize) -> Windows<'_, T> { - assert_ne!(size, 0); + let size = NonZeroUsize::new(size).expect("size is zero"); Windows::new(self, size) } diff --git a/src/test/codegen/slice-windows-no-bounds-check.rs b/src/test/codegen/slice-windows-no-bounds-check.rs new file mode 100644 index 0000000000000..4f5f4425c271c --- /dev/null +++ b/src/test/codegen/slice-windows-no-bounds-check.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] + +// compile-flags: -O + +use std::slice::Windows; + +// CHECK-LABEL: @naive_string_search +#[no_mangle] +pub fn naive_string_search(haystack: &str, needle: &str) -> Option { + if needle.is_empty() { + return Some(0); + } + // CHECK-NOT: panic + // CHECK-NOT: fail + haystack + .as_bytes() + .windows(needle.len()) + .position(|sub| sub == needle.as_bytes()) +} + +// CHECK-LABEL: @next +#[no_mangle] +pub fn next<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> { + // CHECK-NOT: panic + // CHECK-NOT: fail + w.next() +} + +// CHECK-LABEL: @next_back +#[no_mangle] +pub fn next_back<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> { + // CHECK-NOT: panic + // CHECK-NOT: fail + w.next_back() +}