Skip to content

Commit

Permalink
Asserts the maximum value that can be returned from Vec::len
Browse files Browse the repository at this point in the history
  • Loading branch information
EFanZh authored and gitbot committed Feb 20, 2025
1 parent 79ab9db commit 2f2c17f
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
11 changes: 9 additions & 2 deletions alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@
#[cfg(not(no_global_oom_handling))]
use core::cmp;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
#[cfg(not(no_global_oom_handling))]
use core::iter;
Expand All @@ -65,6 +64,7 @@ use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::{self, Index, IndexMut, Range, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
use core::{fmt, intrinsics};

#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
pub use self::extract_if::ExtractIf;
Expand Down Expand Up @@ -2680,7 +2680,14 @@ impl<T, A: Allocator> Vec<T, A> {
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
#[rustc_confusables("length", "size")]
pub const fn len(&self) -> usize {
self.len
let len = self.len;

// SAFETY: The maximum capacity of `Vec<T>` is `isize::MAX` bytes, so the maximum value can
// be returned is `usize::checked_div(mem::size_of::<T>()).unwrap_or(usize::MAX)`, which
// matches the definition of `T::MAX_SLICE_LEN`.
unsafe { intrinsics::assume(len <= T::MAX_SLICE_LEN) };

len
}

/// Returns `true` if the vector contains no elements.
Expand Down
11 changes: 11 additions & 0 deletions core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,17 @@ pub trait SizedTypeProperties: Sized {
#[doc(hidden)]
#[unstable(feature = "sized_type_properties", issue = "none")]
const LAYOUT: Layout = Layout::new::<Self>();

/// The largest safe length for a `[Self]`.
///
/// Anything larger than this would make `size_of_val` overflow `isize::MAX`,
/// which is never allowed for a single object.
#[doc(hidden)]
#[unstable(feature = "sized_type_properties", issue = "none")]
const MAX_SLICE_LEN: usize = match size_of::<Self>() {
0 => usize::MAX,
n => (isize::MAX as usize) / n,
};
}
#[doc(hidden)]
#[unstable(feature = "sized_type_properties", issue = "none")]
Expand Down

0 comments on commit 2f2c17f

Please sign in to comment.