Skip to content

Commit ada8fc8

Browse files
committed
Auto merge of #123575 - scottmcm:assume-raw-parts, r=<try>
Add some targeted `assume(bytes <= isize::MAX)` around slices Putting it on every single slice length was pretty expensive, but let's see if doing it just in `slice::from_raw_parts(_mut)` ~~and `slice::Iter(Mut)::len`~~ works better.
2 parents 4e431fa + 5c95280 commit ada8fc8

File tree

3 files changed

+19
-11
lines changed

3 files changed

+19
-11
lines changed

library/core/src/mem/mod.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,17 @@ pub trait SizedTypeProperties: Sized {
12351235
#[doc(hidden)]
12361236
#[unstable(feature = "sized_type_properties", issue = "none")]
12371237
const IS_ZST: bool = size_of::<Self>() == 0;
1238+
1239+
/// The largest safe length for a `[Self]`.
1240+
///
1241+
/// Anything larger than this would make `size_of_val` overflow `isize::MAX`,
1242+
/// which is never allowed for a single object.
1243+
#[doc(hidden)]
1244+
#[unstable(feature = "sized_type_properties", issue = "none")]
1245+
const MAX_SLICE_LEN: usize = match size_of::<Self>() {
1246+
0 => usize::MAX,
1247+
n => (isize::MAX as usize) / n,
1248+
};
12381249
}
12391250
#[doc(hidden)]
12401251
#[unstable(feature = "sized_type_properties", issue = "none")]

library/core/src/slice/raw.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Free functions to create `&[T]` and `&mut [T]`.
22
33
use crate::array;
4-
use crate::mem::{align_of, size_of};
4+
use crate::intrinsics;
5+
use crate::mem::{align_of, SizedTypeProperties};
56
use crate::ops::Range;
67
use crate::ptr;
78
use crate::ub_checks;
@@ -98,13 +99,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
9899
"slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
99100
(
100101
data: *mut () = data as *mut (),
101-
size: usize = size_of::<T>(),
102102
align: usize = align_of::<T>(),
103103
len: usize = len,
104+
max_len: usize = T::MAX_SLICE_LEN,
104105
) =>
105106
ub_checks::is_aligned_and_not_null(data, align)
106-
&& ub_checks::is_valid_allocation_size(size, len)
107+
&& len <= max_len
107108
);
109+
intrinsics::assume(len <= T::MAX_SLICE_LEN);
108110
&*ptr::slice_from_raw_parts(data, len)
109111
}
110112
}
@@ -152,13 +154,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m
152154
"slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
153155
(
154156
data: *mut () = data as *mut (),
155-
size: usize = size_of::<T>(),
156157
align: usize = align_of::<T>(),
157158
len: usize = len,
159+
max_len: usize = T::MAX_SLICE_LEN,
158160
) =>
159161
ub_checks::is_aligned_and_not_null(data, align)
160-
&& ub_checks::is_valid_allocation_size(size, len)
162+
&& len <= max_len
161163
);
164+
intrinsics::assume(len <= T::MAX_SLICE_LEN);
162165
&mut *ptr::slice_from_raw_parts_mut(data, len)
163166
}
164167
}

library/core/src/ub_checks.rs

-6
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,6 @@ pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize) -> boo
115115
!ptr.is_null() && ptr.is_aligned_to(align)
116116
}
117117

118-
#[inline]
119-
pub(crate) const fn is_valid_allocation_size(size: usize, len: usize) -> bool {
120-
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };
121-
len <= max_len
122-
}
123-
124118
/// Checks whether the regions of memory starting at `src` and `dst` of size
125119
/// `count * size` do *not* overlap.
126120
///

0 commit comments

Comments
 (0)