Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit339f266

Browse files
committed
Redo SliceIndex implementations
1 parentc3c1757 commit339f266

File tree

1 file changed

+86
-32
lines changed

1 file changed

+86
-32
lines changed

‎core/src/slice/index.rs‎

Lines changed: 86 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
usecrate::intrinsics::const_eval_select;
44
usecrate::ops;
5-
usecrate::ptr;
65
usecrate::ub_checks::assert_unsafe_precondition;
76

87
#[stable(feature ="rust1", since ="1.0.0")]
@@ -106,6 +105,47 @@ const fn slice_end_index_overflow_fail() -> ! {
106105
panic!("attempted to index slice up to maximum usize");
107106
}
108107

108+
// The UbChecks are great for catching bugs in the unsafe methods, but including
109+
// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
110+
// Both the safe and unsafe public methods share these helpers,
111+
// which use intrinsics directly to get *no* extra checks.
112+
113+
#[inline(always)]
114+
constunsafefnget_noubcheck<T>(ptr:*const[T],index:usize) ->*constT{
115+
let ptr = ptras*constT;
116+
// SAFETY: The caller already checked these preconditions
117+
unsafe{crate::intrinsics::offset(ptr, index)}
118+
}
119+
120+
#[inline(always)]
121+
constunsafefnget_mut_noubcheck<T>(ptr:*mut[T],index:usize) ->*mutT{
122+
let ptr = ptras*mutT;
123+
// SAFETY: The caller already checked these preconditions
124+
unsafe{crate::intrinsics::offset(ptr, index)}
125+
}
126+
127+
#[inline(always)]
128+
constunsafefnget_offset_len_noubcheck<T>(
129+
ptr:*const[T],
130+
offset:usize,
131+
len:usize,
132+
) ->*const[T]{
133+
// SAFETY: The caller already checked these preconditions
134+
let ptr =unsafe{get_noubcheck(ptr, offset)};
135+
crate::intrinsics::aggregate_raw_ptr(ptr, len)
136+
}
137+
138+
#[inline(always)]
139+
constunsafefnget_offset_len_mut_noubcheck<T>(
140+
ptr:*mut[T],
141+
offset:usize,
142+
len:usize,
143+
) ->*mut[T]{
144+
// SAFETY: The caller already checked these preconditions
145+
let ptr =unsafe{get_mut_noubcheck(ptr, offset)};
146+
crate::intrinsics::aggregate_raw_ptr(ptr, len)
147+
}
148+
109149
mod private_slice_index{
110150
usesuper::ops;
111151
#[stable(feature ="slice_get_slice", since ="1.28.0")]
@@ -203,13 +243,17 @@ unsafe impl<T> SliceIndex<[T]> for usize {
203243
#[inline]
204244
fnget(self,slice:&[T]) ->Option<&T>{
205245
// SAFETY: `self` is checked to be in bounds.
206-
ifself < slice.len(){unsafe{Some(&*self.get_unchecked(slice))}}else{None}
246+
ifself < slice.len(){unsafe{Some(&*get_noubcheck(slice,self))}}else{None}
207247
}
208248

209249
#[inline]
210250
fnget_mut(self,slice:&mut[T]) ->Option<&mutT>{
211-
// SAFETY: `self` is checked to be in bounds.
212-
ifself < slice.len(){unsafe{Some(&mut*self.get_unchecked_mut(slice))}}else{None}
251+
ifself < slice.len(){
252+
// SAFETY: `self` is checked to be in bounds.
253+
unsafe{Some(&mut*get_mut_noubcheck(slice,self))}
254+
}else{
255+
None
256+
}
213257
}
214258

215259
#[inline]
@@ -227,7 +271,7 @@ unsafe impl<T> SliceIndex<[T]> for usize {
227271
// Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
228272
// precondition of this function twice.
229273
crate::intrinsics::assume(self < slice.len());
230-
slice.as_ptr().add(self)
274+
get_noubcheck(slice,self)
231275
}
232276
}
233277

@@ -239,7 +283,7 @@ unsafe impl<T> SliceIndex<[T]> for usize {
239283
(this:usize =self, len:usize = slice.len()) => this < len
240284
);
241285
// SAFETY: see comments for `get_unchecked` above.
242-
unsafe{slice.as_mut_ptr().add(self)}
286+
unsafe{get_mut_noubcheck(slice,self)}
243287
}
244288

245289
#[inline]
@@ -265,7 +309,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
265309
fnget(self,slice:&[T]) ->Option<&[T]>{
266310
ifself.end() <= slice.len(){
267311
// SAFETY: `self` is checked to be valid and in bounds above.
268-
unsafe{Some(&*self.get_unchecked(slice))}
312+
unsafe{Some(&*get_offset_len_noubcheck(slice,self.start(),self.len()))}
269313
}else{
270314
None
271315
}
@@ -275,7 +319,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
275319
fnget_mut(self,slice:&mut[T]) ->Option<&mut[T]>{
276320
ifself.end() <= slice.len(){
277321
// SAFETY: `self` is checked to be valid and in bounds above.
278-
unsafe{Some(&mut*self.get_unchecked_mut(slice))}
322+
unsafe{Some(&mut*get_offset_len_mut_noubcheck(slice,self.start(),self.len()))}
279323
}else{
280324
None
281325
}
@@ -292,7 +336,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
292336
// cannot be longer than `isize::MAX`. They also guarantee that
293337
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
294338
// so the call to `add` is safe.
295-
unsafe{ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()),self.len())}
339+
unsafe{get_offset_len_noubcheck(slice,self.start(),self.len())}
296340
}
297341

298342
#[inline]
@@ -304,14 +348,14 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
304348
);
305349

306350
// SAFETY: see comments for `get_unchecked` above.
307-
unsafe{ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()),self.len())}
351+
unsafe{get_offset_len_mut_noubcheck(slice,self.start(),self.len())}
308352
}
309353

310354
#[inline]
311355
fnindex(self,slice:&[T]) ->&[T]{
312356
ifself.end() <= slice.len(){
313357
// SAFETY: `self` is checked to be valid and in bounds above.
314-
unsafe{&*self.get_unchecked(slice)}
358+
unsafe{&*get_offset_len_noubcheck(slice,self.start(),self.len())}
315359
}else{
316360
slice_end_index_len_fail(self.end(), slice.len())
317361
}
@@ -321,7 +365,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::IndexRange {
321365
fnindex_mut(self,slice:&mut[T]) ->&mut[T]{
322366
ifself.end() <= slice.len(){
323367
// SAFETY: `self` is checked to be valid and in bounds above.
324-
unsafe{&mut*self.get_unchecked_mut(slice)}
368+
unsafe{&mut*get_offset_len_mut_noubcheck(slice,self.start(),self.len())}
325369
}else{
326370
slice_end_index_len_fail(self.end(), slice.len())
327371
}
@@ -338,21 +382,26 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
338382

339383
#[inline]
340384
fnget(self,slice:&[T]) ->Option<&[T]>{
341-
ifself.start >self.end ||self.end > slice.len(){
342-
None
343-
}else{
385+
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
386+
ifletSome(new_len) = usize::checked_sub(self.end,self.start)
387+
&&self.end <= slice.len()
388+
{
344389
// SAFETY: `self` is checked to be valid and in bounds above.
345-
unsafe{Some(&*self.get_unchecked(slice))}
390+
unsafe{Some(&*get_offset_len_noubcheck(slice,self.start, new_len))}
391+
}else{
392+
None
346393
}
347394
}
348395

349396
#[inline]
350397
fnget_mut(self,slice:&mut[T]) ->Option<&mut[T]>{
351-
ifself.start >self.end ||self.end > slice.len(){
352-
None
353-
}else{
398+
ifletSome(new_len) = usize::checked_sub(self.end,self.start)
399+
&&self.end <= slice.len()
400+
{
354401
// SAFETY: `self` is checked to be valid and in bounds above.
355-
unsafe{Some(&mut*self.get_unchecked_mut(slice))}
402+
unsafe{Some(&mut*get_offset_len_mut_noubcheck(slice,self.start, new_len))}
403+
}else{
404+
None
356405
}
357406
}
358407

@@ -373,8 +422,10 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
373422
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
374423
// so the call to `add` is safe and the length calculation cannot overflow.
375424
unsafe{
376-
let new_len =self.end.unchecked_sub(self.start);
377-
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), new_len)
425+
// Using the intrinsic avoids a superfluous UB check,
426+
// since the one on this method already checked `end >= start`.
427+
let new_len =crate::intrinsics::unchecked_sub(self.end,self.start);
428+
get_offset_len_noubcheck(slice,self.start, new_len)
378429
}
379430
}
380431

@@ -391,31 +442,34 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
391442
);
392443
// SAFETY: see comments for `get_unchecked` above.
393444
unsafe{
394-
let new_len =self.end.unchecked_sub(self.start);
395-
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), new_len)
445+
let new_len =crate::intrinsics::unchecked_sub(self.end,self.start);
446+
get_offset_len_mut_noubcheck(slice,self.start, new_len)
396447
}
397448
}
398449

399450
#[inline(always)]
400451
fnindex(self,slice:&[T]) ->&[T]{
401-
ifself.start >self.end{
402-
slice_index_order_fail(self.start,self.end);
403-
}elseifself.end > slice.len(){
452+
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
453+
letSome(new_len) = usize::checked_sub(self.end,self.start)else{
454+
slice_index_order_fail(self.start,self.end)
455+
};
456+
ifself.end > slice.len(){
404457
slice_end_index_len_fail(self.end, slice.len());
405458
}
406459
// SAFETY: `self` is checked to be valid and in bounds above.
407-
unsafe{&*self.get_unchecked(slice)}
460+
unsafe{&*get_offset_len_noubcheck(slice,self.start, new_len)}
408461
}
409462

410463
#[inline]
411464
fnindex_mut(self,slice:&mut[T]) ->&mut[T]{
412-
ifself.start >self.end{
413-
slice_index_order_fail(self.start,self.end);
414-
}elseifself.end > slice.len(){
465+
letSome(new_len) = usize::checked_sub(self.end,self.start)else{
466+
slice_index_order_fail(self.start,self.end)
467+
};
468+
ifself.end > slice.len(){
415469
slice_end_index_len_fail(self.end, slice.len());
416470
}
417471
// SAFETY: `self` is checked to be valid and in bounds above.
418-
unsafe{&mut*self.get_unchecked_mut(slice)}
472+
unsafe{&mut*get_offset_len_mut_noubcheck(slice,self.start, new_len)}
419473
}
420474
}
421475

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp