Skip to content

Commit 2f2c17f

Browse files
EFanZhgitbot
authored and
gitbot
committed
Asserts the maximum value that can be returned from Vec::len
1 parent 79ab9db commit 2f2c17f

File tree

2 files changed

+20
-2
lines changed

2 files changed

+20
-2
lines changed

alloc/src/vec/mod.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
#[cfg(not(no_global_oom_handling))]
5757
use core::cmp;
5858
use core::cmp::Ordering;
59-
use core::fmt;
6059
use core::hash::{Hash, Hasher};
6160
#[cfg(not(no_global_oom_handling))]
6261
use core::iter;
@@ -65,6 +64,7 @@ use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
6564
use core::ops::{self, Index, IndexMut, Range, RangeBounds};
6665
use core::ptr::{self, NonNull};
6766
use core::slice::{self, SliceIndex};
67+
use core::{fmt, intrinsics};
6868

6969
#[unstable(feature = "extract_if", reason = "recently added", issue = "43244")]
7070
pub use self::extract_if::ExtractIf;
@@ -2680,7 +2680,14 @@ impl<T, A: Allocator> Vec<T, A> {
26802680
#[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
26812681
#[rustc_confusables("length", "size")]
26822682
pub const fn len(&self) -> usize {
2683-
self.len
2683+
let len = self.len;
2684+
2685+
// SAFETY: The maximum capacity of `Vec<T>` is `isize::MAX` bytes, so the maximum value can
2686+
// be returned is `usize::checked_div(mem::size_of::<T>()).unwrap_or(usize::MAX)`, which
2687+
// matches the definition of `T::MAX_SLICE_LEN`.
2688+
unsafe { intrinsics::assume(len <= T::MAX_SLICE_LEN) };
2689+
2690+
len
26842691
}
26852692

26862693
/// Returns `true` if the vector contains no elements.

core/src/mem/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,17 @@ pub trait SizedTypeProperties: Sized {
12411241
#[doc(hidden)]
12421242
#[unstable(feature = "sized_type_properties", issue = "none")]
12431243
const LAYOUT: Layout = Layout::new::<Self>();
1244+
1245+
/// The largest safe length for a `[Self]`.
1246+
///
1247+
/// Anything larger than this would make `size_of_val` overflow `isize::MAX`,
1248+
/// which is never allowed for a single object.
1249+
#[doc(hidden)]
1250+
#[unstable(feature = "sized_type_properties", issue = "none")]
1251+
const MAX_SLICE_LEN: usize = match size_of::<Self>() {
1252+
0 => usize::MAX,
1253+
n => (isize::MAX as usize) / n,
1254+
};
12441255
}
12451256
#[doc(hidden)]
12461257
#[unstable(feature = "sized_type_properties", issue = "none")]

0 commit comments

Comments
 (0)