diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 419bf0e292ae1..39cfef73efc6a 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -11,7 +11,6 @@ use crate::intrinsics::{assume, exact_div, unchecked_sub};
 use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
 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};
@@ -1193,12 +1192,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: NonZeroUsize,
+    size: usize,
 }
 
 impl<'a, T: 'a> Windows<'a, T> {
     #[inline]
-    pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self {
+    pub(super) fn new(slice: &'a [T], size: usize) -> Self {
         Self { v: slice, size }
     }
 }
@@ -1217,10 +1216,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
-        if self.size.get() > self.v.len() {
+        if self.size > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[..self.size.get()]);
+            let ret = Some(&self.v[..self.size]);
             self.v = &self.v[1..];
             ret
         }
@@ -1228,10 +1227,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.size.get() > self.v.len() {
+        if self.size > self.v.len() {
             (0, Some(0))
         } else {
-            let size = self.v.len() - self.size.get() + 1;
+            let size = self.v.len() - self.size + 1;
             (size, Some(size))
         }
     }
@@ -1243,7 +1242,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<Self::Item> {
-        let (end, overflow) = self.size.get().overflowing_add(n);
+        let (end, overflow) = self.size.overflowing_add(n);
         if end > self.v.len() || overflow {
             self.v = &[];
             None
@@ -1256,10 +1255,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn last(self) -> Option<Self::Item> {
-        if self.size.get() > self.v.len() {
+        if self.size > self.v.len() {
             None
         } else {
-            let start = self.v.len() - self.size.get();
+            let start = self.v.len() - self.size;
             Some(&self.v[start..])
         }
     }
@@ -1270,7 +1269,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.get()) }
+        unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) }
     }
 }
 
@@ -1278,10 +1277,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.get() > self.v.len() {
+        if self.size > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[self.v.len() - self.size.get()..]);
+            let ret = Some(&self.v[self.v.len() - self.size..]);
             self.v = &self.v[..self.v.len() - 1];
             ret
         }
@@ -1290,11 +1289,11 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
     #[inline]
     fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         let (end, overflow) = self.v.len().overflowing_sub(n);
-        if end < self.size.get() || overflow {
+        if end < self.size || overflow {
             self.v = &[];
             None
         } else {
-            let ret = &self.v[end - self.size.get()..end];
+            let ret = &self.v[end - self.size..end];
             self.v = &self.v[..end - 1];
             Some(ret)
         }
@@ -1995,7 +1994,7 @@ pub struct ArrayWindows<'a, T: 'a, const N: usize> {
 impl<'a, T: 'a, const N: usize> ArrayWindows<'a, T, N> {
     #[inline]
     pub(super) fn new(slice: &'a [T]) -> Self {
-        let num_windows = slice.len().saturating_sub(N - 1);
+        let num_windows = (slice.len() + 1).saturating_sub(N);
         Self { slice_head: slice.as_ptr(), num: num_windows, marker: PhantomData }
     }
 }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 67eecab99d89a..aece1a9865e06 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -11,7 +11,6 @@
 use crate::cmp::Ordering::{self, 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};
@@ -725,13 +724,9 @@ impl<T> [T] {
     }
 
     /// Returns an iterator over all contiguous windows of length
-    /// `size`. The windows overlap. If the slice is shorter than
+    /// `size`. The windows may overlap. If the slice is shorter than
     /// `size`, the iterator returns no values.
     ///
-    /// # Panics
-    ///
-    /// Panics if `size` is 0.
-    ///
     /// # Examples
     ///
     /// ```
@@ -753,7 +748,6 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn windows(&self, size: usize) -> Windows<'_, T> {
-        let size = NonZeroUsize::new(size).expect("size is zero");
         Windows::new(self, size)
     }
 
@@ -1199,11 +1193,6 @@ impl<T> [T] {
     ///
     /// If `N` is greater than the size of the slice, it will return no windows.
     ///
-    /// # Panics
-    ///
-    /// Panics if `N` is 0. This check will most probably get changed to a compile time
-    /// error before this method gets stabilized.
-    ///
     /// # Examples
     ///
     /// ```
@@ -1220,7 +1209,6 @@ impl<T> [T] {
     #[unstable(feature = "array_windows", issue = "75027")]
     #[inline]
     pub fn array_windows<const N: usize>(&self) -> ArrayWindows<'_, T, N> {
-        assert_ne!(N, 0);
         ArrayWindows::new(self)
     }
 
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 240b894057c3e..ca5b8d08db3e2 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -726,6 +726,18 @@ fn test_array_windows_infer() {
     assert_eq!(total, 3 + 6 + 9 + 12 + 15);
 }
 
+#[test]
+fn test_array_windows_zero() {
+    let v: &[i32] = &[0, 1, 2];
+    let mut iter = v.array_windows::<0>();
+
+    assert_eq!(iter.next(), Some(&[]));
+    assert_eq!(iter.next(), Some(&[]));
+    assert_eq!(iter.next(), Some(&[]));
+    assert_eq!(iter.next(), Some(&[]));
+    assert_eq!(iter.next(), None);
+}
+
 #[test]
 fn test_array_windows_count() {
     let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@@ -739,6 +751,10 @@ fn test_array_windows_count() {
     let v3: &[i32] = &[];
     let c3 = v3.array_windows::<2>();
     assert_eq!(c3.count(), 0);
+
+    let v4: &[i32] = &[0, 1, 2];
+    let c4 = c4.array_windows::<0>();
+    assert_eq!(c4.count(), 4);
 }
 
 #[test]
@@ -1050,6 +1066,10 @@ fn test_windows_count() {
     let v3: &[i32] = &[];
     let c3 = v3.windows(2);
     assert_eq!(c3.count(), 0);
+
+    let v4: &[i32] = &[0, 1, 2, 3, 4];
+    let c4 = v4.windows(0);
+    assert_eq!(c4.count(), 6);
 }
 
 #[test]