From 606be3f5dd308b2b3e5e7da53793b8e5bcfd9ba7 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Mon, 10 Aug 2026 01:07:55 +0200 Subject: [PATCH 1/8] tidy: enforce documented unsafe --- src/tools/tidy/src/style.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index af82e8b6d22cf..e779577ad8f07 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -522,11 +522,14 @@ fn check_file_style(check: &mut RunningCheck, file: &Path, contents: &str) { err("Don't use magic numbers that spell things (consider 0x12345678)"); } } - // for now we just check libcore + // Only check library crates. if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment - && file.components().any(|c| c.as_os_str() == "core") + && file.components().any(|c| { + let c = c.as_os_str(); + c == "core" || c == "alloc" || c == "std" + }) && !is_test { suppressible_tidy_err!(err, ignore.undocumented_unsafe, "undocumented unsafe"); From 377fedef5fee5a4f4b4f100d8e3e3b6bb386056a Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 11 Aug 2026 20:03:39 +0200 Subject: [PATCH 2/8] safety comments in alloc --- library/alloc/src/alloc.rs | 8 ++ library/alloc/src/boxed.rs | 33 +++++++ library/alloc/src/boxed/convert.rs | 12 +++ library/alloc/src/boxed/thin.rs | 11 +++ .../alloc/src/collections/binary_heap/mod.rs | 7 ++ library/alloc/src/collections/btree/map.rs | 18 ++++ library/alloc/src/collections/btree/mem.rs | 2 + .../alloc/src/collections/btree/navigate.rs | 24 +++++ library/alloc/src/collections/btree/node.rs | 76 ++++++++++++++++ library/alloc/src/collections/btree/remove.rs | 3 + library/alloc/src/collections/btree/search.rs | 13 +++ library/alloc/src/collections/btree/set.rs | 5 ++ library/alloc/src/collections/linked_list.rs | 44 +++++++++ .../alloc/src/collections/vec_deque/drain.rs | 9 ++ .../src/collections/vec_deque/extract_if.rs | 1 + .../alloc/src/collections/vec_deque/iter.rs | 1 + .../src/collections/vec_deque/iter_mut.rs | 1 + .../alloc/src/collections/vec_deque/mod.rs | 73 +++++++++++++++ .../src/collections/vec_deque/spec_extend.rs | 7 ++ .../alloc/src/collections/vec_deque/splice.rs | 5 ++ library/alloc/src/ffi/c_str.rs | 15 ++++ library/alloc/src/io/buf_read.rs | 1 + library/alloc/src/io/buffered/bufreader.rs | 1 + library/alloc/src/io/buffered/bufwriter.rs | 1 + library/alloc/src/io/cursor.rs | 4 + library/alloc/src/io/error.rs | 2 + library/alloc/src/io/read.rs | 3 + library/alloc/src/io/util.rs | 1 + library/alloc/src/raw_vec/mod.rs | 20 +++++ library/alloc/src/rc.rs | 84 +++++++++++++++++ library/alloc/src/slice.rs | 4 + library/alloc/src/str.rs | 16 ++++ library/alloc/src/string.rs | 16 ++++ library/alloc/src/sync.rs | 89 +++++++++++++++++++ library/alloc/src/task.rs | 8 ++ library/alloc/src/vec/drain.rs | 7 ++ library/alloc/src/vec/extract_if.rs | 3 + library/alloc/src/vec/in_place_collect.rs | 8 ++ library/alloc/src/vec/in_place_drop.rs | 3 + library/alloc/src/vec/into_iter.rs | 21 +++++ library/alloc/src/vec/is_zero.rs | 1 + library/alloc/src/vec/mod.rs | 33 +++++++ library/alloc/src/vec/spec_extend.rs | 2 + library/alloc/src/vec/spec_from_elem.rs | 2 + library/alloc/src/vec/spec_from_iter.rs | 1 + .../alloc/src/vec/spec_from_iter_nested.rs | 1 + library/alloc/src/vec/splice.rs | 5 ++ library/alloc/src/wtf8/mod.rs | 16 ++++ 48 files changed, 721 insertions(+) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 49bf941984af5..2cdf4ca003c49 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -116,6 +116,7 @@ pub struct Global; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc(layout: Layout) -> *mut u8 { + // SAFETY: Untriaged. unsafe { // Make sure we don't accidentally allow omitting the allocator shim in // stable code until it is actually stabilized. @@ -159,6 +160,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { + // SAFETY: Untriaged. unsafe { dealloc_nonnull(NonNull::new_unchecked(ptr), layout) } } @@ -166,6 +168,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn dealloc_nonnull(ptr: NonNull, layout: Layout) { + // SAFETY: Untriaged. unsafe { __rust_dealloc(ptr, layout.size(), layout.alignment()) } } @@ -212,6 +215,7 @@ unsafe fn dealloc_nonnull(ptr: NonNull, layout: Layout) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: Untriaged. unsafe { realloc_nonnull(NonNull::new_unchecked(ptr), layout, new_size) } } @@ -219,6 +223,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn realloc_nonnull(ptr: NonNull, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: Untriaged. unsafe { __rust_realloc(ptr, layout.size(), layout.alignment(), new_size) } } @@ -276,6 +281,7 @@ unsafe fn realloc_nonnull(ptr: NonNull, layout: Layout, new_size: usize) -> #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { + // SAFETY: Untriaged. unsafe { // Make sure we don't accidentally allow omitting the allocator shim in // stable code until it is actually stabilized. @@ -519,6 +525,7 @@ impl Global { cmp::min(old_layout.size(), new_layout.size()), ); } + // SAFETY: Untriaged. unsafe { self.deallocate_impl(ptr, old_layout); } @@ -633,6 +640,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { #[inline] fn rt_error(layout: Layout) -> ! { + // SAFETY: Untriaged. unsafe { __rust_alloc_error_handler(layout.size(), layout.align()); } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index cd2508a76a10e..bb4537cb64888 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -266,6 +266,7 @@ const fn box_new_uninit(layout: Layout) -> *mut u8 { pub const fn box_assume_init_into_vec_unsafe( b: Box>, ) -> crate::vec::Vec { + // SAFETY: Untriaged. unsafe { (b.assume_init() as Box<[T]>).into_vec() } } @@ -450,6 +451,7 @@ impl Box { if size_of::() == size_of::() && align_of::() == align_of::() { let (value, allocation) = Box::take(this); Box::write( + // SAFETY: Untriaged. unsafe { mem::transmute::>, Box>>(allocation) }, f(value), ) @@ -490,6 +492,7 @@ impl Box { let (value, allocation) = Box::take(this); try { Box::write( + // SAFETY: Untriaged. unsafe { mem::transmute::>, Box>>( allocation, @@ -528,6 +531,7 @@ impl Box { { let mut boxed = Self::new_uninit_in(alloc); boxed.write(x); + // SAFETY: Untriaged. unsafe { boxed.assume_init() } } @@ -554,6 +558,7 @@ impl Box { { let mut boxed = Self::try_new_uninit_in(alloc)?; boxed.write(x); + // SAFETY: Untriaged. unsafe { Ok(boxed.assume_init()) } } @@ -618,6 +623,7 @@ impl Box { let layout = Layout::new::>(); alloc.allocate(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } } @@ -690,6 +696,7 @@ impl Box { let layout = Layout::new::>(); alloc.allocate_zeroed(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } } @@ -726,6 +733,7 @@ impl Box { #[unstable(feature = "box_into_boxed_slice", issue = "71582")] pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(boxed); + // SAFETY: Untriaged. unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } } @@ -769,6 +777,7 @@ impl Box { /// ``` #[unstable(feature = "box_take", issue = "147212")] pub fn take(boxed: Self) -> (T, Box, A>) { + // SAFETY: Untriaged. unsafe { let (raw, alloc) = Box::into_non_null_with_allocator(boxed); let value = raw.read(); @@ -873,6 +882,7 @@ impl Box { fn drop(&mut self) { let &mut DeallocDropGuard(layout, alloc, ptr) = self; // Safety: `ptr` was allocated by `*alloc` with layout `layout` + // SAFETY: Untriaged. unsafe { alloc.deallocate(ptr, layout); } @@ -890,12 +900,14 @@ impl Box { // Safety: `*ptr` is newly allocated, correctly aligned to `align_of_val(src)`, // and is valid for writes for `size_of_val(src)`. // If this panics, then `guard` will deallocate for us (if allocation occuured) + // SAFETY: Untriaged. unsafe { ::clone_to_uninit(src, ptr); } // Defuse the deallocate guard core::mem::forget(guard); // Safety: We just initialized `*ptr` as a clone of `src` + // SAFETY: Untriaged. Ok(unsafe { Box::from_raw_in(ptr.with_metadata_of(src), alloc) }) } } @@ -919,6 +931,7 @@ impl Box<[T]> { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { RawVec::with_capacity(len).into_box(len) } } @@ -942,6 +955,7 @@ impl Box<[T]> { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } } @@ -975,6 +989,7 @@ impl Box<[T]> { }; Global.allocate(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } @@ -1009,6 +1024,7 @@ impl Box<[T]> { }; Global.allocate_zeroed(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, Global).into_box(len)) } } } @@ -1036,6 +1052,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { RawVec::with_capacity_in(len, alloc).into_box(len) } } @@ -1063,6 +1080,7 @@ impl Box<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Box<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { RawVec::with_capacity_zeroed_in(len, alloc).into_box(len) } } @@ -1101,6 +1119,7 @@ impl Box<[T], A> { }; alloc.allocate(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -1140,6 +1159,7 @@ impl Box<[T], A> { }; alloc.allocate_zeroed(layout)?.cast() }; + // SAFETY: Untriaged. unsafe { Ok(RawVec::from_raw_parts_in(ptr.as_ptr(), len, alloc).into_box(len)) } } @@ -1237,6 +1257,7 @@ impl Box, A> { #[stable(feature = "box_uninit_write", since = "1.87.0")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box { + // SAFETY: Untriaged. unsafe { (*boxed).write(value); boxed.assume_init() @@ -1273,6 +1294,7 @@ impl Box<[mem::MaybeUninit], A> { #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); + // SAFETY: Untriaged. unsafe { Box::from_raw_in(raw as *mut [T], alloc) } } } @@ -1326,6 +1348,7 @@ impl Box { #[inline] #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_raw(raw: *mut T) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_raw_in(raw, Global) } } @@ -1378,6 +1401,7 @@ impl Box { #[inline] #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_non_null(ptr: NonNull) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_raw(ptr.as_ptr()) } } @@ -1557,6 +1581,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { + // SAFETY: Untriaged. Box(unsafe { Unique::new_unchecked(raw) }, alloc) } @@ -1675,6 +1700,7 @@ impl Box { // In case `A` *is* `Global`, this does not quite have the right behavior; `into_raw` // works around that. let ptr = &raw mut **b; + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&b.1) }; (ptr, alloc) } @@ -1742,6 +1768,7 @@ impl Box { #[doc(hidden)] pub fn into_unique(b: Self) -> (Unique, A) { let (ptr, alloc) = Box::into_raw_with_allocator(b); + // SAFETY: Untriaged. unsafe { (Unique::from(&mut *ptr), alloc) } } @@ -1940,6 +1967,7 @@ impl Box { { let (ptr, alloc) = Box::into_raw_with_allocator(b); mem::forget(alloc); + // SAFETY: Untriaged. unsafe { &mut *ptr } } @@ -1981,6 +2009,7 @@ impl Box { // It's not possible to move or replace the insides of a `Pin>` // when `T: !Unpin`, so it's safe to pin it directly without any // additional requirements. + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(boxed) } } } @@ -1993,6 +2022,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box { let ptr = self.0; + // SAFETY: Untriaged. unsafe { let layout = Layout::for_value_raw(ptr.as_ptr()); if layout.size() != 0 { @@ -2009,6 +2039,7 @@ impl Default for Box { #[inline] fn default() -> Self { let mut x: Box> = Box::new_uninit(); + // SAFETY: Untriaged. unsafe { // SAFETY: `x` is valid for writing and has the same layout as `T`. // If `T::default()` panics, dropping `x` will just deallocate the Box as `MaybeUninit` @@ -2084,6 +2115,7 @@ impl Clone for Box { fn clone(&self) -> Self { // Pre-allocate memory to allow writing the cloned value directly. let mut boxed = Self::new_uninit_in(self.1.clone()); + // SAFETY: Untriaged. unsafe { (**self).clone_to_uninit(boxed.as_mut_ptr().cast()); boxed.assume_init() @@ -2154,6 +2186,7 @@ impl Clone for Box { fn clone(&self) -> Self { // this makes a copy of the data let buf: Box<[u8]> = self.as_bytes().into(); + // SAFETY: Untriaged. unsafe { from_boxed_utf8_unchecked(buf) } } } diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index d6a8e78991b84..4ab9a796297c6 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -217,6 +217,7 @@ impl From> for Box<[u8], A> { #[inline] fn from(s: Box) -> Self { let (raw, alloc) = Box::into_raw_with_allocator(s); + // SAFETY: Untriaged. unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } } } @@ -270,6 +271,7 @@ impl TryFrom> for Box<[T; N]> { /// `boxed_slice.len()` does not equal `N`. fn try_from(boxed_slice: Box<[T]>) -> Result { if boxed_slice.len() == N { + // SAFETY: Untriaged. Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) } else { Err(boxed_slice) @@ -303,6 +305,7 @@ impl TryFrom> for Box<[T; N]> { fn try_from(vec: Vec) -> Result { if vec.len() == N { let boxed_slice = vec.into_boxed_slice(); + // SAFETY: Untriaged. Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) } else { Err(vec) @@ -331,6 +334,7 @@ impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { + // SAFETY: Untriaged. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -362,6 +366,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); + // SAFETY: Untriaged. unsafe { let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); Box::from_raw_in(raw as *mut T, alloc) @@ -390,6 +395,7 @@ impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { + // SAFETY: Untriaged. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -421,6 +427,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); + // SAFETY: Untriaged. unsafe { let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); Box::from_raw_in(raw as *mut T, alloc) @@ -449,6 +456,7 @@ impl Box { #[inline] #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast(self) -> Result, Self> { + // SAFETY: Untriaged. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -480,6 +488,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); + // SAFETY: Untriaged. unsafe { let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = Box::into_raw_with_allocator(self); @@ -709,6 +718,7 @@ impl dyn Error { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { if self.is::() { + // SAFETY: Untriaged. unsafe { let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) @@ -726,6 +736,7 @@ impl dyn Error + Send { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; + // SAFETY: Untriaged. ::downcast(err).map_err(|s| unsafe { // Reapply the `Send` marker. mem::transmute::, Box>(s) @@ -740,6 +751,7 @@ impl dyn Error + Send + Sync { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; + // SAFETY: Untriaged. ::downcast(err).map_err(|s| unsafe { // Reapply the `Send + Sync` markers. mem::transmute::, Box>(s) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 22c3d89e3ccdb..44d3eeee89d78 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -146,6 +146,7 @@ impl Deref for ThinBox { let value = self.data(); let metadata = self.meta(); let pointer = ptr::from_raw_parts(value as *const (), metadata); + // SAFETY: Untriaged. unsafe { &*pointer } } } @@ -156,6 +157,7 @@ impl DerefMut for ThinBox { let value = self.data(); let metadata = self.meta(); let pointer = ptr::from_raw_parts_mut::(value as *mut (), metadata); + // SAFETY: Untriaged. unsafe { &mut *pointer } } } @@ -163,6 +165,7 @@ impl DerefMut for ThinBox { #[unstable(feature = "thin_box", issue = "92791")] impl Drop for ThinBox { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { let value = self.deref_mut(); let value = value as *mut T; @@ -176,6 +179,7 @@ impl ThinBox { fn meta(&self) -> ::Metadata { // Safety: // - NonNull and valid. + // SAFETY: Untriaged. unsafe { *self.with_header().header() } } @@ -238,6 +242,7 @@ impl WithHeader { alloc::handle_alloc_error(Layout::new::<()>()); }; + // SAFETY: Untriaged. unsafe { // Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so // we use `layout.dangling()` for this case, which should have a valid @@ -275,6 +280,7 @@ impl WithHeader { return Err(core::alloc::AllocError); }; + // SAFETY: Untriaged. unsafe { // Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so // we use `layout.dangling()` for this case, which should have a valid @@ -330,6 +336,7 @@ impl WithHeader { let alloc_size = max(align_of::(), size_of::<::Metadata>()); + // SAFETY: Untriaged. unsafe { // SAFETY: align is power of two because it is the maximum of two alignments. let alloc: *mut u8 = const_allocate(alloc_size, alloc_align); @@ -350,6 +357,7 @@ impl WithHeader { // SAFETY: `alloc` points to `::Metadata`, so addition stays in-bounds. let value_ptr = +// SAFETY: Untriaged. unsafe { (alloc as *const ::Metadata).add(1) }.cast::().cast_mut(); debug_assert!(value_ptr.is_aligned()); mem::forget(value); @@ -373,6 +381,7 @@ impl WithHeader { return; } + // SAFETY: Untriaged. unsafe { // SAFETY: Layout must have been computable if we're in drop let (layout, value_offset) = @@ -385,6 +394,7 @@ impl WithHeader { } } + // SAFETY: Untriaged. unsafe { // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. let _guard = DropGuard { @@ -407,6 +417,7 @@ impl WithHeader { // needed to align the header. Subtracting the header size from the aligned data pointer // will always result in an aligned header pointer, it just may not point to the // beginning of the allocation. + // SAFETY: Untriaged. let hp = unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }; debug_assert!(hp.is_aligned()); hp diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 98192e1fb5b01..8f6435299bdb3 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -327,6 +327,7 @@ impl Deref for PeekMut<'_, T, A> { fn deref(&self) -> &T { debug_assert!(!self.heap.is_empty()); // SAFE: PeekMut is only instantiated for non-empty heaps + // SAFETY: Untriaged. unsafe { self.heap.data.get_unchecked(0) } } } @@ -346,6 +347,7 @@ impl DerefMut for PeekMut<'_, T, A> { // // This is technique is described throughout several other places in // the standard library as "leak amplification". + // SAFETY: Untriaged. unsafe { // SAFETY: len > 1 so len != 0. self.original_len = Some(NonZero::new_unchecked(len)); @@ -356,6 +358,7 @@ impl DerefMut for PeekMut<'_, T, A> { } // SAFE: PeekMut is only instantiated for non-empty heaps + // SAFETY: Untriaged. unsafe { self.heap.data.get_unchecked_mut(0) } } } @@ -1537,6 +1540,7 @@ impl<'a, T> Hole<'a, T> { unsafe fn new(data: &'a mut [T], pos: usize) -> Self { debug_assert!(pos < data.len()); // SAFE: pos should be inside the slice + // SAFETY: Untriaged. let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; Hole { data, elt: ManuallyDrop::new(elt), pos } } @@ -1559,6 +1563,7 @@ impl<'a, T> Hole<'a, T> { unsafe fn get(&self, index: usize) -> &T { debug_assert!(index != self.pos); debug_assert!(index < self.data.len()); + // SAFETY: Untriaged. unsafe { self.data.get_unchecked(index) } } @@ -1569,6 +1574,7 @@ impl<'a, T> Hole<'a, T> { unsafe fn move_to(&mut self, index: usize) { debug_assert!(index != self.pos); debug_assert!(index < self.data.len()); + // SAFETY: Untriaged. unsafe { let ptr = self.data.as_mut_ptr(); let index_ptr: *const _ = ptr.add(index); @@ -1583,6 +1589,7 @@ impl Drop for Hole<'_, T> { #[inline] fn drop(&mut self) { // fill the hole again + // SAFETY: Untriaged. unsafe { let pos = self.pos; ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 0a1f7738632c1..291b3dd42170a 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -205,6 +205,7 @@ pub struct BTreeMap< #[stable(feature = "btree_drop", since = "1.7.0")] unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTreeMap { fn drop(&mut self) { + // SAFETY: Untriaged. drop(unsafe { ptr::read(self) }.into_iter()) } } @@ -279,6 +280,7 @@ impl Clone for BTreeMap { // We can't destructure subtree directly // because BTreeMap implements Drop + // SAFETY: Untriaged. let (subroot, sublength) = unsafe { let subtree = ManuallyDrop::new(subtree); let root = ptr::read(&subtree.root); @@ -1324,6 +1326,7 @@ impl BTreeMap { // apply 'f' to get a new (K, V), and insert it back // into the next entry that the cursor is pointing at let v = conflict(&k, v, first_other_val); + // SAFETY: Untriaged. unsafe { self_cursor.insert_after_unchecked(k, v) }; } } @@ -1360,6 +1363,7 @@ impl BTreeMap { // apply 'f' to get a new (K, V), and insert it back // into the next entry that the cursor is pointing at let v = conflict(&k, v, other_val); + // SAFETY: Untriaged. unsafe { self_cursor.insert_after_unchecked(k, v) }; } break; @@ -1737,6 +1741,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.next_unchecked() }) } } @@ -1774,6 +1779,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.next_back_unchecked() }) } } @@ -1815,6 +1821,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.next_unchecked() }) } } @@ -1849,6 +1856,7 @@ impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.next_back_unchecked() }) } } @@ -1889,12 +1897,14 @@ impl IntoIterator for BTreeMap { IntoIter { range: full_range, length: me.length, + // SAFETY: Untriaged. alloc: unsafe { ManuallyDrop::take(&mut me.alloc) }, } } else { IntoIter { range: LazyLeafRange::none(), length: 0, + // SAFETY: Untriaged. alloc: unsafe { ManuallyDrop::take(&mut me.alloc) }, } } @@ -1937,6 +1947,7 @@ impl IntoIter { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.deallocating_next_unchecked(self.alloc.clone()) }) } } @@ -1951,6 +1962,7 @@ impl IntoIter { None } else { self.length -= 1; + // SAFETY: Untriaged. Some(unsafe { self.range.deallocating_next_back_unchecked(self.alloc.clone()) }) } } @@ -3347,6 +3359,7 @@ impl<'a, K, V, A> CursorMutKey<'a, K, V, A> { let (k, v) = unsafe { kv.reborrow_mut().into_kv_mut() }; let (k, v) = (k as *mut _, v as *mut _); self.current = Some(kv.next_leaf_edge()); + // SAFETY: Untriaged. Some(unsafe { (&mut *k, &mut *v) }) } Err(root) => { @@ -3372,6 +3385,7 @@ impl<'a, K, V, A> CursorMutKey<'a, K, V, A> { let (k, v) = unsafe { kv.reborrow_mut().into_kv_mut() }; let (k, v) = (k as *mut _, v as *mut _); self.current = Some(kv.next_back_leaf_edge()); + // SAFETY: Untriaged. Some(unsafe { (&mut *k, &mut *v) }) } Err(root) => { @@ -3534,6 +3548,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { return Err(UnorderedKeyError {}); } } + // SAFETY: Untriaged. unsafe { self.insert_after_unchecked(key, value); } @@ -3562,6 +3577,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { return Err(UnorderedKeyError {}); } } + // SAFETY: Untriaged. unsafe { self.insert_before_unchecked(key, value); } @@ -3643,6 +3659,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { /// * All keys in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, key: K, value: V) { + // SAFETY: Untriaged. unsafe { self.inner.insert_after_unchecked(key, value) } } @@ -3661,6 +3678,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { /// * All keys in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, key: K, value: V) { + // SAFETY: Untriaged. unsafe { self.inner.insert_before_unchecked(key, value) } } diff --git a/library/alloc/src/collections/btree/mem.rs b/library/alloc/src/collections/btree/mem.rs index 4643c4133d55d..674083ac6ae09 100644 --- a/library/alloc/src/collections/btree/mem.rs +++ b/library/alloc/src/collections/btree/mem.rs @@ -23,8 +23,10 @@ pub(super) fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { } } let guard = PanicGuard; + // SAFETY: Untriaged. let value = unsafe { ptr::read(v) }; let (new_value, ret) = change(value); + // SAFETY: Untriaged. unsafe { ptr::write(v, new_value); } diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index b2a7de74875d9..880507928d72a 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -57,11 +57,13 @@ impl<'a, K, V> LeafRange, K, V> { impl<'a, K, V> LeafRange, K, V> { #[inline] pub(super) fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + // SAFETY: Untriaged. self.perform_next_checked(|kv| unsafe { ptr::read(kv) }.into_kv_valmut()) } #[inline] pub(super) fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> { + // SAFETY: Untriaged. self.perform_next_back_checked(|kv| unsafe { ptr::read(kv) }.into_kv_valmut()) } } @@ -158,11 +160,13 @@ impl LazyLeafRange { impl<'a, K, V> LazyLeafRange, K, V> { #[inline] pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { + // SAFETY: Untriaged. unsafe { self.init_front().unwrap().next_unchecked() } } #[inline] pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { + // SAFETY: Untriaged. unsafe { self.init_back().unwrap().next_back_unchecked() } } } @@ -170,11 +174,13 @@ impl<'a, K, V> LazyLeafRange, K, V> { impl<'a, K, V> LazyLeafRange, K, V> { #[inline] pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { + // SAFETY: Untriaged. unsafe { self.init_front().unwrap().next_unchecked() } } #[inline] pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { + // SAFETY: Untriaged. unsafe { self.init_back().unwrap().next_back_unchecked() } } } @@ -196,6 +202,7 @@ impl LazyLeafRange { ) -> Handle, marker::KV> { debug_assert!(self.front.is_some()); let front = self.init_front().unwrap(); + // SAFETY: Untriaged. unsafe { front.deallocating_next_unchecked(alloc) } } @@ -206,6 +213,7 @@ impl LazyLeafRange { ) -> Handle, marker::KV> { debug_assert!(self.back.is_some()); let back = self.init_back().unwrap(); + // SAFETY: Untriaged. unsafe { back.deallocating_next_back_unchecked(alloc) } } @@ -222,6 +230,7 @@ impl LazyLeafRange { &mut self, ) -> Option<&mut Handle, marker::Edge>> { if let Some(LazyLeafHandle::Root(root)) = &self.front { + // SAFETY: Untriaged. self.front = Some(LazyLeafHandle::Edge(unsafe { ptr::read(root) }.first_leaf_edge())); } match &mut self.front { @@ -236,6 +245,7 @@ impl LazyLeafRange { &mut self, ) -> Option<&mut Handle, marker::Edge>> { if let Some(LazyLeafHandle::Root(root)) = &self.back { + // SAFETY: Untriaged. self.back = Some(LazyLeafHandle::Edge(unsafe { ptr::read(root) }.last_leaf_edge())); } match &mut self.back { @@ -279,7 +289,9 @@ impl NodeRef { + // SAFETY: Untriaged. let mut lower_edge = unsafe { Handle::new_edge(ptr::read(&node), lower_edge_idx) }; + // SAFETY: Untriaged. let mut upper_edge = unsafe { Handle::new_edge(node, upper_edge_idx) }; loop { match (lower_edge.force(), upper_edge.force()) { @@ -345,6 +357,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> K: Borrow, R: RangeBounds, { + // SAFETY: Untriaged. unsafe { self.find_leaf_edges_spanning_range(range) } } @@ -354,6 +367,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> pub(super) fn full_range(self) -> LazyLeafRange, K, V> { // We duplicate the root NodeRef here -- we will never visit the same KV // twice, and never end up with overlapping value references. + // SAFETY: Untriaged. let self2 = unsafe { ptr::read(&self) }; full_range(self, self2) } @@ -366,6 +380,7 @@ impl NodeRef { pub(super) fn full_range(self) -> LazyLeafRange { // We duplicate the root NodeRef here -- we will never access it in a way // that overlaps references obtained from the root. + // SAFETY: Untriaged. let self2 = unsafe { ptr::read(&self) }; full_range(self, self2) } @@ -464,8 +479,10 @@ impl Handle, marker::Edge> { let mut edge = self.forget_node_type(); loop { edge = match edge.right_kv() { + // SAFETY: Untriaged. Ok(kv) => return Some((unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)), Err(last_edge) => { + // SAFETY: Untriaged. match unsafe { last_edge.into_node().deallocate_and_ascend(alloc.clone()) } { Some(parent_edge) => parent_edge.forget_node_type(), None => return None, @@ -496,8 +513,10 @@ impl Handle, marker::Edge> { let mut edge = self.forget_node_type(); loop { edge = match edge.left_kv() { + // SAFETY: Untriaged. Ok(kv) => return Some((unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)), Err(last_edge) => { + // SAFETY: Untriaged. match unsafe { last_edge.into_node().deallocate_and_ascend(alloc.clone()) } { Some(parent_edge) => parent_edge.forget_node_type(), None => return None, @@ -516,6 +535,7 @@ impl Handle, marker::Edge> { fn deallocating_end(self, alloc: A) { let mut edge = self.forget_node_type(); while let Some(parent_edge) = + // SAFETY: Untriaged. unsafe { edge.into_node().deallocate_and_ascend(alloc.clone()) } { edge = parent_edge.forget_node_type(); @@ -558,6 +578,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_kv().ok().unwrap(); + // SAFETY: Untriaged. (unsafe { ptr::read(&kv) }.next_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. @@ -572,6 +593,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::E unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { let kv = super::mem::replace(self, |leaf_edge| { let kv = leaf_edge.next_back_kv().ok().unwrap(); + // SAFETY: Untriaged. (unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv) }); // Doing this last is faster, according to benchmarks. @@ -596,6 +618,7 @@ impl Handle, marker::Edge> { &mut self, alloc: A, ) -> Handle, marker::KV> { + // SAFETY: Untriaged. super::mem::replace(self, |leaf_edge| unsafe { leaf_edge.deallocating_next(alloc).unwrap() }) @@ -617,6 +640,7 @@ impl Handle, marker::Edge> { &mut self, alloc: A, ) -> Handle, marker::KV> { + // SAFETY: Untriaged. super::mem::replace(self, |leaf_edge| unsafe { leaf_edge.deallocating_next_back(alloc).unwrap() }) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 84dd4b7e49def..6ba7042b389ad 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -75,6 +75,7 @@ impl LeafNode { unsafe fn init(this: *mut Self) { // As a general policy, we leave fields uninitialized if they can be, as this should // be both slightly faster and easier to track in Valgrind. + // SAFETY: Untriaged. unsafe { // parent_idx, keys, and vals are all MaybeUninit (&raw mut (*this).parent).write(None); @@ -85,6 +86,7 @@ impl LeafNode { /// Creates a new boxed `LeafNode`. fn new(alloc: A) -> Box { let mut leaf = Box::new_uninit_in(alloc); + // SAFETY: Untriaged. unsafe { // SAFETY: `leaf` points to a `LeafNode` LeafNode::init(leaf.as_mut_ptr()); @@ -119,6 +121,7 @@ impl InternalNode { /// such an edge. unsafe fn new(alloc: A) -> Box { let mut node = Box::::new_uninit_in(alloc); + // SAFETY: Untriaged. unsafe { // SAFETY: argument points to the `node.data` `LeafNode` LeafNode::init(&raw mut (*node.as_mut_ptr()).data); @@ -235,6 +238,7 @@ impl NodeRef { impl NodeRef { /// Creates a new internal (height > 0) `NodeRef` fn new_internal(child: Root, alloc: A) -> Self { + // SAFETY: Untriaged. let mut new_node = unsafe { InternalNode::new(alloc) }; new_node.edges[0].write(child.node); NodeRef::from_new_internal(new_node, NonZero::new(child.height + 1).unwrap()) @@ -275,6 +279,7 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { /// Borrows exclusive access to the data of an internal node. fn as_internal_mut(&mut self) -> &mut InternalNode { let ptr = Self::as_internal_ptr(self); + // SAFETY: Untriaged. unsafe { &mut *ptr } } } @@ -287,6 +292,7 @@ impl NodeRef { pub(super) fn len(&self) -> usize { // Crucially, we only access the `len` field here. If BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. + // SAFETY: Untriaged. unsafe { usize::from((*Self::as_leaf_ptr(self)).len) } } @@ -335,10 +341,12 @@ impl NodeRef // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. let leaf_ptr: *const _ = Self::as_leaf_ptr(&self); + // SAFETY: Untriaged. unsafe { (*leaf_ptr).parent } .as_ref() .map(|parent| Handle { node: NodeRef::from_internal(*parent, self.height + 1), + // SAFETY: Untriaged. idx: unsafe { usize::from((*leaf_ptr).parent_idx.assume_init()) }, _marker: PhantomData, }) @@ -346,11 +354,13 @@ impl NodeRef } pub(super) fn first_edge(self) -> Handle { + // SAFETY: Untriaged. unsafe { Handle::new_edge(self, 0) } } pub(super) fn last_edge(self) -> Handle { let len = self.len(); + // SAFETY: Untriaged. unsafe { Handle::new_edge(self, len) } } @@ -358,6 +368,7 @@ impl NodeRef pub(super) fn first_kv(self) -> Handle { let len = self.len(); assert!(len > 0); + // SAFETY: Untriaged. unsafe { Handle::new_kv(self, 0) } } @@ -365,6 +376,7 @@ impl NodeRef pub(super) fn last_kv(self) -> Handle { let len = self.len(); assert!(len > 0); + // SAFETY: Untriaged. unsafe { Handle::new_kv(self, len - 1) } } } @@ -393,6 +405,7 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { /// Borrows a view into the keys stored in the node. pub(super) fn keys(&self) -> &[K] { let leaf = self.into_leaf(); + // SAFETY: Untriaged. unsafe { leaf.keys.get_unchecked(..usize::from(leaf.len)).assume_init_ref() } } } @@ -408,6 +421,7 @@ impl NodeRef { let height = self.height; let node = self.node; let ret = self.ascend().ok(); + // SAFETY: Untriaged. unsafe { alloc.deallocate( node.cast(), @@ -533,12 +547,16 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { // to avoid aliasing with outstanding references to other elements, // in particular, those returned to the caller in earlier iterations. let leaf = Self::as_leaf_ptr(&mut self); + // SAFETY: Untriaged. let keys = unsafe { &raw const (*leaf).keys }; + // SAFETY: Untriaged. let vals = unsafe { &raw mut (*leaf).vals }; // We must coerce to unsized array pointers because of Rust issue #74679. let keys: *const [_] = keys; let vals: *mut [_] = vals; + // SAFETY: Untriaged. let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; + // SAFETY: Untriaged. let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; (key, val) } @@ -557,12 +575,14 @@ impl<'a, K, V> NodeRef, K, V, marker::Internal> { unsafe fn correct_childrens_parent_links>(&mut self, range: R) { for i in range { debug_assert!(i <= self.len()); + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.reborrow_mut(), i) }.correct_parent_link(); } } fn correct_all_childrens_parent_links(&mut self) { let len = self.len(); + // SAFETY: Untriaged. unsafe { self.correct_childrens_parent_links(0..=len) }; } } @@ -572,7 +592,9 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// without invalidating other references to the node. fn set_parent_link(&mut self, parent: NonNull>, parent_idx: usize) { let leaf = Self::as_leaf_ptr(self); + // SAFETY: Untriaged. unsafe { (*leaf).parent = Some(parent) }; + // SAFETY: Untriaged. unsafe { (*leaf).parent_idx.write(parent_idx as u16) }; } } @@ -627,6 +649,7 @@ impl NodeRef { self.height -= 1; self.clear_parent_link(); + // SAFETY: Untriaged. unsafe { alloc.deallocate(top.cast(), Layout::new::>()); } @@ -669,6 +692,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Leaf> { let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; + // SAFETY: Untriaged. unsafe { self.key_area_mut(idx).write(key); self.val_area_mut(idx).write(val); @@ -697,6 +721,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { let idx = usize::from(*len); assert!(idx < CAPACITY); *len += 1; + // SAFETY: Untriaged. unsafe { self.key_area_mut(idx).write(key); self.val_area_mut(idx).write(val); @@ -805,10 +830,12 @@ impl Handle, mar } pub(super) fn left_edge(self) -> Handle, marker::Edge> { + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.node, self.idx) } } pub(super) fn right_edge(self) -> Handle, marker::Edge> { + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.node, self.idx + 1) } } } @@ -844,6 +871,7 @@ impl<'a, K, V, NodeType, HandleType> Handle, K, V, NodeT &mut self, ) -> Handle, K, V, NodeType>, HandleType> { // We can't use Handle::new_kv or Handle::new_edge because we don't know our type + // SAFETY: Untriaged. Handle { node: unsafe { self.node.reborrow_mut() }, idx: self.idx, _marker: PhantomData } } @@ -867,6 +895,7 @@ impl Handle( self, ) -> Handle, K, V, NodeType>, HandleType> { + // SAFETY: Untriaged. Handle { node: unsafe { self.node.awaken() }, idx: self.idx, _marker: PhantomData } } } @@ -884,6 +913,7 @@ impl Handle, mar self, ) -> Result, marker::KV>, Self> { if self.idx > 0 { + // SAFETY: Untriaged. Ok(unsafe { Handle::new_kv(self.node, self.idx - 1) }) } else { Err(self) @@ -894,6 +924,7 @@ impl Handle, mar self, ) -> Result, marker::KV>, Self> { if self.idx < self.node.len() { + // SAFETY: Untriaged. Ok(unsafe { Handle::new_kv(self.node, self.idx) }) } else { Err(self) @@ -934,6 +965,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark debug_assert!(self.node.len() < CAPACITY); let new_len = self.node.len() + 1; + // SAFETY: Untriaged. unsafe { slice_insert(self.node.key_area_mut(..new_len), self.idx, key); slice_insert(self.node.val_area_mut(..new_len), self.idx, val); @@ -965,12 +997,15 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark (None, handle.dormant()) } else { let (middle_kv_idx, insertion) = splitpoint(self.idx); + // SAFETY: Untriaged. let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; let mut result = middle.split(alloc); let insertion_edge = match insertion { + // SAFETY: Untriaged. LeftOrRight::Left(insert_idx) => unsafe { Handle::new_edge(result.left.reborrow_mut(), insert_idx) }, + // SAFETY: Untriaged. LeftOrRight::Right(insert_idx) => unsafe { Handle::new_edge(result.right.borrow_mut(), insert_idx) }, @@ -988,6 +1023,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: /// links to. This is useful when the ordering of edges has been changed, fn correct_parent_link(self) { // Create backpointer without invalidating other references to the node. + // SAFETY: Untriaged. let ptr = unsafe { NonNull::new_unchecked(NodeRef::as_internal_ptr(&self.node)) }; let idx = self.idx; let mut child = self.descend(); @@ -1004,6 +1040,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, debug_assert!(edge.height == self.node.height - 1); let new_len = self.node.len() + 1; + // SAFETY: Untriaged. unsafe { slice_insert(self.node.key_area_mut(..new_len), self.idx, key); slice_insert(self.node.val_area_mut(..new_len), self.idx, val); @@ -1031,12 +1068,15 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, None } else { let (middle_kv_idx, insertion) = splitpoint(self.idx); + // SAFETY: Untriaged. let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) }; let mut result = middle.split(alloc); let mut insertion_edge = match insertion { + // SAFETY: Untriaged. LeftOrRight::Left(insert_idx) => unsafe { Handle::new_edge(result.left.reborrow_mut(), insert_idx) }, + // SAFETY: Untriaged. LeftOrRight::Right(insert_idx) => unsafe { Handle::new_edge(result.right.borrow_mut(), insert_idx) }, @@ -1112,6 +1152,7 @@ impl // reference (Rust issue #73987) and invalidate any other references // to or inside the array, should any be around. let parent_ptr = NodeRef::as_internal_ptr(&self.node); + // SAFETY: Untriaged. let node = unsafe { (*parent_ptr).edges.get_unchecked(self.idx).assume_init_read() }; NodeRef { node, height: self.node.height - 1, _marker: PhantomData } } @@ -1121,7 +1162,9 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeTyp pub(super) fn into_kv(self) -> (&'a K, &'a V) { debug_assert!(self.idx < self.node.len()); let leaf = self.node.into_leaf(); + // SAFETY: Untriaged. let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() }; + // SAFETY: Untriaged. let v = unsafe { leaf.vals.get_unchecked(self.idx).assume_init_ref() }; (k, v) } @@ -1129,19 +1172,23 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeTyp impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { pub(super) fn key_mut(&mut self) -> &mut K { + // SAFETY: Untriaged. unsafe { self.node.key_area_mut(self.idx).assume_init_mut() } } pub(super) fn into_val_mut(self) -> &'a mut V { debug_assert!(self.idx < self.node.len()); let leaf = self.node.into_leaf_mut(); + // SAFETY: Untriaged. unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() } } pub(super) fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { debug_assert!(self.idx < self.node.len()); let leaf = self.node.into_leaf_mut(); + // SAFETY: Untriaged. let k = unsafe { leaf.keys.get_unchecked_mut(self.idx).assume_init_mut() }; + // SAFETY: Untriaged. let v = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }; (k, v) } @@ -1149,6 +1196,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::KV> { pub(super) fn into_kv_valmut(self) -> (&'a K, &'a mut V) { + // SAFETY: Untriaged. unsafe { self.node.into_key_val_mut_at(self.idx) } } } @@ -1158,6 +1206,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> debug_assert!(self.idx < self.node.len()); // We cannot call separate key and value methods, because calling the second one // invalidates the reference returned by the first. + // SAFETY: Untriaged. unsafe { let leaf = self.node.as_leaf_mut(); let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_mut(); @@ -1180,6 +1229,7 @@ impl Handle, marker::KV> pub(super) unsafe fn into_key_val(mut self) -> (K, V) { debug_assert!(self.idx < self.node.len()); let leaf = self.node.as_leaf_dying(); + // SAFETY: Untriaged. unsafe { let key = leaf.keys.get_unchecked_mut(self.idx).assume_init_read(); let val = leaf.vals.get_unchecked_mut(self.idx).assume_init_read(); @@ -1197,6 +1247,7 @@ impl Handle, marker::KV> impl Drop for Dropper<'_, T> { #[inline] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { self.0.assume_init_drop(); } @@ -1205,6 +1256,7 @@ impl Handle, marker::KV> debug_assert!(self.idx < self.node.len()); let leaf = self.node.as_leaf_dying(); + // SAFETY: Untriaged. unsafe { let key = leaf.keys.get_unchecked_mut(self.idx); let val = leaf.vals.get_unchecked_mut(self.idx); @@ -1223,6 +1275,7 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType> let old_len = self.node.len(); let new_len = old_len - self.idx - 1; new_node.len = new_len as u16; + // SAFETY: Untriaged. unsafe { let k = self.node.key_area_mut(self.idx).assume_init_read(); let v = self.node.val_area_mut(self.idx).assume_init_read(); @@ -1268,6 +1321,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark mut self, ) -> ((K, V), Handle, K, V, marker::Leaf>, marker::Edge>) { let old_len = self.node.len(); + // SAFETY: Untriaged. unsafe { let k = slice_remove(self.node.key_area_mut(..old_len), self.idx); let v = slice_remove(self.node.val_area_mut(..old_len), self.idx); @@ -1290,6 +1344,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, alloc: A, ) -> SplitResult<'a, K, V, marker::Internal> { let old_len = self.node.len(); + // SAFETY: Untriaged. unsafe { let mut new_node = InternalNode::new(alloc); let kv = self.split_leaf_data(&mut new_node.data); @@ -1318,7 +1373,9 @@ pub(super) struct BalancingContext<'a, K, V> { impl<'a, K, V> Handle, K, V, marker::Internal>, marker::KV> { pub(super) fn consider_for_balancing(self) -> BalancingContext<'a, K, V> { + // SAFETY: Untriaged. let self1 = unsafe { ptr::read(&self) }; + // SAFETY: Untriaged. let self2 = unsafe { ptr::read(&self) }; BalancingContext { parent: self, @@ -1344,15 +1401,18 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { /// the right, instead of shifting at least N of the sibling's elements to /// the left. pub(super) fn choose_parent_kv(self) -> Result>, Self> { + // SAFETY: Untriaged. match unsafe { ptr::read(&self) }.ascend() { Ok(parent_edge) => match parent_edge.left_kv() { Ok(left_parent_kv) => Ok(LeftOrRight::Left(BalancingContext { + // SAFETY: Untriaged. parent: unsafe { ptr::read(&left_parent_kv) }, left_child: left_parent_kv.left_edge().descend(), right_child: self, })), Err(parent_edge) => match parent_edge.right_kv() { Ok(right_parent_kv) => Ok(LeftOrRight::Right(BalancingContext { + // SAFETY: Untriaged. parent: unsafe { ptr::read(&right_parent_kv) }, left_child: self, right_child: right_parent_kv.right_edge().descend(), @@ -1413,6 +1473,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { assert!(new_left_len <= CAPACITY); + // SAFETY: Untriaged. unsafe { *left_node.len_mut() = new_left_len as u16; @@ -1497,6 +1558,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { LeftOrRight::Left(idx) => idx, LeftOrRight::Right(idx) => old_left_len + 1 + idx, }; + // SAFETY: Untriaged. unsafe { Handle::new_edge(child, new_idx) } } @@ -1509,6 +1571,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { track_right_edge_idx: usize, ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { self.bulk_steal_left(1); + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.right_child, 1 + track_right_edge_idx) } } @@ -1521,12 +1584,14 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { track_left_edge_idx: usize, ) -> Handle, K, V, marker::LeafOrInternal>, marker::Edge> { self.bulk_steal_right(1); + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.left_child, track_left_edge_idx) } } /// This does stealing similar to `steal_left` but steals multiple elements at once. pub(super) fn bulk_steal_left(&mut self, count: usize) { assert!(count > 0); + // SAFETY: Untriaged. unsafe { let left_node = &mut self.left_child; let old_left_len = left_node.len(); @@ -1590,6 +1655,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { /// The symmetric clone of `bulk_steal_left`. pub(super) fn bulk_steal_right(&mut self, count: usize) { assert!(count > 0); + // SAFETY: Untriaged. unsafe { let left_node = &mut self.left_child; let old_left_len = left_node.len(); @@ -1656,6 +1722,7 @@ impl Handle, marker::E pub(super) fn forget_node_type( self, ) -> Handle, marker::Edge> { + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } } } @@ -1664,6 +1731,7 @@ impl Handle, marke pub(super) fn forget_node_type( self, ) -> Handle, marker::Edge> { + // SAFETY: Untriaged. unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } } } @@ -1672,6 +1740,7 @@ impl Handle, marker::K pub(super) fn forget_node_type( self, ) -> Handle, marker::KV> { + // SAFETY: Untriaged. unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } } } @@ -1700,6 +1769,7 @@ impl<'a, K, V, Type> Handle, K, V, marker::LeafOrInterna pub(super) unsafe fn cast_to_leaf_unchecked( self, ) -> Handle, K, V, marker::Leaf>, Type> { + // SAFETY: Untriaged. let node = unsafe { self.node.cast_to_leaf_unchecked() }; Handle { node, idx: self.idx, _marker: PhantomData } } @@ -1712,6 +1782,7 @@ impl<'a, K, V> Handle, K, V, marker::LeafOrInternal>, ma &mut self, right: &mut NodeRef, K, V, marker::LeafOrInternal>, ) { + // SAFETY: Untriaged. unsafe { let new_left_len = self.idx; let mut left_node = self.reborrow_mut().into_node(); @@ -1820,6 +1891,7 @@ pub(super) mod marker { /// # Safety /// The slice has more than `idx` elements. unsafe fn slice_insert(slice: &mut [MaybeUninit], idx: usize, val: T) { + // SAFETY: Untriaged. unsafe { let len = slice.len(); debug_assert!(len > idx); @@ -1837,6 +1909,7 @@ unsafe fn slice_insert(slice: &mut [MaybeUninit], idx: usize, val: T) { /// # Safety /// The slice has more than `idx` elements. unsafe fn slice_remove(slice: &mut [MaybeUninit], idx: usize) -> T { + // SAFETY: Untriaged. unsafe { let len = slice.len(); debug_assert!(idx < len); @@ -1852,6 +1925,7 @@ unsafe fn slice_remove(slice: &mut [MaybeUninit], idx: usize) -> T { /// # Safety /// The slice has at least `distance` elements. unsafe fn slice_shl(slice: &mut [MaybeUninit], distance: usize) { + // SAFETY: Untriaged. unsafe { let slice_ptr = slice.as_mut_ptr(); ptr::copy(slice_ptr.add(distance), slice_ptr, slice.len() - distance); @@ -1863,6 +1937,7 @@ unsafe fn slice_shl(slice: &mut [MaybeUninit], distance: usize) { /// # Safety /// The slice has at least `distance` elements. unsafe fn slice_shr(slice: &mut [MaybeUninit], distance: usize) { + // SAFETY: Untriaged. unsafe { let slice_ptr = slice.as_mut_ptr(); ptr::copy(slice_ptr, slice_ptr.add(distance), slice.len() - distance); @@ -1874,6 +1949,7 @@ unsafe fn slice_shr(slice: &mut [MaybeUninit], distance: usize) { /// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`. fn move_to_slice(src: &mut [MaybeUninit], dst: &mut [MaybeUninit]) { assert!(src.len() == dst.len()); + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len()); } diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs index 9d870b86f34a0..81344631d007f 100644 --- a/library/alloc/src/collections/btree/remove.rs +++ b/library/alloc/src/collections/btree/remove.rs @@ -53,6 +53,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark right_parent_kv.steal_right(idx) } } + // SAFETY: Untriaged. Err(pos) => unsafe { Handle::new_edge(pos, idx) }, }; // SAFETY: `new_pos` is the leaf we started from or a sibling. @@ -85,11 +86,13 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, // the element we were asked to remove. Prefer the left adjacent KV, // for the reasons listed in `choose_parent_kv`. let left_leaf_kv = self.left_edge().descend().last_leaf_edge().left_kv(); + // SAFETY: Untriaged. let left_leaf_kv = unsafe { left_leaf_kv.ok().unwrap_unchecked() }; let (left_kv, left_hole) = left_leaf_kv.remove_leaf_kv(handle_emptied_internal_root, alloc); // The internal node may have been stolen from or merged. Go back right // to find where the original KV ended up. + // SAFETY: Untriaged. let mut internal = unsafe { left_hole.next_kv().ok().unwrap_unchecked() }; let old_kv = internal.replace_kv(left_kv.0, left_kv.1); let pos = internal.next_leaf_edge(); diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index 96e5bf108024b..ebc61a2dc0b18 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -128,6 +128,7 @@ impl NodeRef NodeRef return Err(common_edge), @@ -165,6 +167,7 @@ impl NodeRef, { let (edge_idx, bound) = self.find_lower_bound_index(bound); + // SAFETY: Untriaged. let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -178,7 +181,9 @@ impl NodeRef, { + // SAFETY: Untriaged. let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; + // SAFETY: Untriaged. let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -200,8 +205,11 @@ impl NodeRef { Q: Ord, K: Borrow, { + // SAFETY: Untriaged. match unsafe { self.find_key_index(key, 0) } { + // SAFETY: Untriaged. IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), + // SAFETY: Untriaged. IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), } } @@ -222,6 +230,7 @@ impl NodeRef { let node = self.reborrow(); let keys = node.keys(); debug_assert!(start_index <= keys.len()); + // SAFETY: Untriaged. for (offset, k) in unsafe { keys.get_unchecked(start_index..) }.iter().enumerate() { match key.cmp(k.borrow()) { Ordering::Greater => {} @@ -246,10 +255,12 @@ impl NodeRef { K: Borrow, { match bound { + // SAFETY: Untriaged. Included(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, + // SAFETY: Untriaged. Excluded(key) => match unsafe { self.find_key_index(key, 0) } { IndexResult::KV(idx) => (idx + 1, AllIncluded), IndexResult::Edge(idx) => (idx, bound), @@ -274,10 +285,12 @@ impl NodeRef { K: Borrow, { match bound { + // SAFETY: Untriaged. Included(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx + 1, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, + // SAFETY: Untriaged. Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { IndexResult::KV(idx) => (idx, AllIncluded), IndexResult::Edge(idx) => (idx, bound), diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 2a483b3d3982e..717661ead0356 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -2303,6 +2303,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, T, A> { + // SAFETY: Untriaged. CursorMutKey { inner: unsafe { self.inner.with_mutable_key() } } } } @@ -2372,6 +2373,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, value: T) { + // SAFETY: Untriaged. unsafe { self.inner.insert_after_unchecked(value, SetValZST) } } @@ -2390,6 +2392,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, value: T) { + // SAFETY: Untriaged. unsafe { self.inner.insert_before_unchecked(value, SetValZST) } } @@ -2458,6 +2461,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, value: T) { + // SAFETY: Untriaged. unsafe { self.inner.insert_after_unchecked(value, SetValZST) } } @@ -2476,6 +2480,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, value: T) { + // SAFETY: Untriaged. unsafe { self.inner.insert_before_unchecked(value, SetValZST) } } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index ca3b2eab30402..6547ed6332ea2 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -173,6 +173,7 @@ impl LinkedList { unsafe fn push_front_node(&mut self, node: NonNull>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. + // SAFETY: Untriaged. unsafe { (*node.as_ptr()).next = self.head; (*node.as_ptr()).prev = None; @@ -194,6 +195,7 @@ impl LinkedList { fn pop_front_node(&mut self) -> Option, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. + // SAFETY: Untriaged. self.head.map(|node| unsafe { let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.head = node.next; @@ -218,6 +220,7 @@ impl LinkedList { unsafe fn push_back_node(&mut self, node: NonNull>) { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. + // SAFETY: Untriaged. unsafe { (*node.as_ptr()).next = None; (*node.as_ptr()).prev = self.tail; @@ -239,6 +242,7 @@ impl LinkedList { fn pop_back_node(&mut self) -> Option, &A>> { // This method takes care not to create mutable references to whole nodes, // to maintain validity of aliasing pointers into `element`. + // SAFETY: Untriaged. self.tail.map(|node| unsafe { let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.tail = node.prev; @@ -262,16 +266,19 @@ impl LinkedList { /// maintain validity of aliasing pointers. #[inline] unsafe fn unlink_node(&mut self, mut node: NonNull>) { + // SAFETY: Untriaged. let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut. // Not creating new mutable (unique!) references overlapping `element`. match node.prev { + // SAFETY: Untriaged. Some(prev) => unsafe { (*prev.as_ptr()).next = node.next }, // this node is the head node None => self.head = node.next, }; match node.next { + // SAFETY: Untriaged. Some(next) => unsafe { (*next.as_ptr()).prev = node.prev }, // this node is the tail node None => self.tail = node.prev, @@ -295,6 +302,7 @@ impl LinkedList { // This method takes care not to create multiple mutable references to whole nodes at the same time, // to maintain validity of aliasing pointers into `element`. if let Some(mut existing_prev) = existing_prev { + // SAFETY: Untriaged. unsafe { existing_prev.as_mut().next = Some(splice_start); } @@ -302,12 +310,14 @@ impl LinkedList { self.head = Some(splice_start); } if let Some(mut existing_next) = existing_next { + // SAFETY: Untriaged. unsafe { existing_next.as_mut().prev = Some(splice_end); } } else { self.tail = Some(splice_end); } + // SAFETY: Untriaged. unsafe { splice_start.as_mut().prev = existing_prev; splice_end.as_mut().next = existing_next; @@ -346,10 +356,12 @@ impl LinkedList { if let Some(mut split_node) = split_node { let first_part_head; let first_part_tail; + // SAFETY: Untriaged. unsafe { first_part_tail = split_node.as_mut().prev.take(); } if let Some(mut tail) = first_part_tail { + // SAFETY: Untriaged. unsafe { tail.as_mut().next = None; } @@ -390,10 +402,12 @@ impl LinkedList { if let Some(mut split_node) = split_node { let second_part_head; let second_part_tail; + // SAFETY: Untriaged. unsafe { second_part_head = split_node.as_mut().next.take(); } if let Some(mut head) = second_part_head { + // SAFETY: Untriaged. unsafe { head.as_mut().prev = None; } @@ -485,6 +499,7 @@ impl LinkedList { // `as_mut` is okay here because we have exclusive access to the entirety // of both lists. if let Some(mut other_head) = other.head.take() { + // SAFETY: Untriaged. unsafe { tail.as_mut().next = Some(other_head); other_head.as_mut().prev = Some(tail); @@ -742,6 +757,7 @@ impl LinkedList { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_confusables("first")] pub fn front(&self) -> Option<&T> { + // SAFETY: Untriaged. unsafe { self.head.as_ref().map(|node| &node.as_ref().element) } } @@ -771,6 +787,7 @@ impl LinkedList { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn front_mut(&mut self) -> Option<&mut T> { + // SAFETY: Untriaged. unsafe { self.head.as_mut().map(|node| &mut node.as_mut().element) } } @@ -794,6 +811,7 @@ impl LinkedList { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn back(&self) -> Option<&T> { + // SAFETY: Untriaged. unsafe { self.tail.as_ref().map(|node| &node.as_ref().element) } } @@ -822,6 +840,7 @@ impl LinkedList { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn back_mut(&mut self) -> Option<&mut T> { + // SAFETY: Untriaged. unsafe { self.tail.as_mut().map(|node| &mut node.as_mut().element) } } @@ -1023,6 +1042,7 @@ impl LinkedList { } iter.tail }; + // SAFETY: Untriaged. unsafe { self.split_off_after_node(split_node, at) } } @@ -1202,6 +1222,7 @@ impl<'a, T> Iterator for Iter<'a, T> { if self.len == 0 { None } else { + // SAFETY: Untriaged. self.head.map(|node| unsafe { // Need an unbound lifetime to get 'a let node = &*node.as_ptr(); @@ -1230,6 +1251,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { if self.len == 0 { None } else { + // SAFETY: Untriaged. self.tail.map(|node| unsafe { // Need an unbound lifetime to get 'a let node = &*node.as_ptr(); @@ -1270,6 +1292,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { if self.len == 0 { None } else { + // SAFETY: Untriaged. self.head.map(|node| unsafe { // Need an unbound lifetime to get 'a let node = &mut *node.as_ptr(); @@ -1298,6 +1321,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { if self.len == 0 { None } else { + // SAFETY: Untriaged. self.tail.map(|node| unsafe { // Need an unbound lifetime to get 'a let node = &mut *node.as_ptr(); @@ -1412,6 +1436,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> { self.index = 0; } // We had a previous element, so let's go to its next + // SAFETY: Untriaged. Some(current) => unsafe { self.current = current.as_ref().next; self.index += 1; @@ -1433,6 +1458,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> { self.index = self.list.len().saturating_sub(1); } // Have a prev. Yield it and go to the previous element. + // SAFETY: Untriaged. Some(current) => unsafe { self.current = current.as_ref().prev; self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); @@ -1448,6 +1474,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> { #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn current(&self) -> Option<&'a T> { + // SAFETY: Untriaged. unsafe { self.current.map(|current| &(*current.as_ptr()).element) } } @@ -1459,6 +1486,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> { #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_next(&self) -> Option<&'a T> { + // SAFETY: Untriaged. unsafe { let next = match self.current { None => self.list.head, @@ -1476,6 +1504,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> { #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_prev(&self) -> Option<&'a T> { + // SAFETY: Untriaged. unsafe { let prev = match self.current { None => self.list.tail, @@ -1539,6 +1568,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { self.index = 0; } // We had a previous element, so let's go to its next + // SAFETY: Untriaged. Some(current) => unsafe { self.current = current.as_ref().next; self.index += 1; @@ -1560,6 +1590,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { self.index = self.list.len().saturating_sub(1); } // Have a prev. Yield it and go to the previous element. + // SAFETY: Untriaged. Some(current) => unsafe { self.current = current.as_ref().prev; self.index = self.index.checked_sub(1).unwrap_or_else(|| self.list.len()); @@ -1575,6 +1606,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn current(&mut self) -> Option<&mut T> { + // SAFETY: Untriaged. unsafe { self.current.map(|current| &mut (*current.as_ptr()).element) } } @@ -1585,6 +1617,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// element of the `LinkedList` then this returns `None`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_next(&mut self) -> Option<&mut T> { + // SAFETY: Untriaged. unsafe { let next = match self.current { None => self.list.head, @@ -1601,6 +1634,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// element of the `LinkedList` then this returns `None`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn peek_prev(&mut self) -> Option<&mut T> { + // SAFETY: Untriaged. unsafe { let prev = match self.current { None => self.list.tail, @@ -1643,6 +1677,7 @@ impl<'a, T> CursorMut<'a, T> { /// inserted at the start of the `LinkedList`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn splice_after(&mut self, list: LinkedList) { + // SAFETY: Untriaged. unsafe { let Some((splice_head, splice_tail, splice_len)) = list.detach_all_nodes() else { return; @@ -1665,6 +1700,7 @@ impl<'a, T> CursorMut<'a, T> { /// inserted at the end of the `LinkedList`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn splice_before(&mut self, list: LinkedList) { + // SAFETY: Untriaged. unsafe { let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() { Some(parts) => parts, @@ -1687,6 +1723,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// inserted at the front of the `LinkedList`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_after(&mut self, item: T) { + // SAFETY: Untriaged. unsafe { let spliced_node = Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; @@ -1708,6 +1745,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { /// inserted at the end of the `LinkedList`. #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn insert_before(&mut self, item: T) { + // SAFETY: Untriaged. unsafe { let spliced_node = Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; @@ -1730,6 +1768,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn remove_current(&mut self) -> Option { let unlinked_node = self.current?; + // SAFETY: Untriaged. unsafe { self.current = unlinked_node.as_ref().next; self.list.unlink_node(unlinked_node); @@ -1751,6 +1790,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { A: Clone, { let mut unlinked_node = self.current?; + // SAFETY: Untriaged. unsafe { self.current = unlinked_node.as_ref().next; self.list.unlink_node(unlinked_node); @@ -1783,6 +1823,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { // The "ghost" non-element's index has changed to 0. self.index = 0; } + // SAFETY: Untriaged. unsafe { self.list.split_off_after_node(self.current, split_off_idx) } } @@ -1799,6 +1840,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { { let split_off_idx = self.index; self.index = 0; + // SAFETY: Untriaged. unsafe { self.list.split_off_before_node(self.current, split_off_idx) } } @@ -1970,6 +2012,7 @@ where fn next(&mut self) -> Option { while let Some(mut node) = self.it { + // SAFETY: Untriaged. unsafe { self.it = node.as_ref().next; self.idx += 1; @@ -1997,6 +2040,7 @@ where A: Allocator, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // SAFETY: Untriaged. let peek = self.it.map(|node| unsafe { &node.as_ref().element }); f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive() } diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index da4b803c64d56..92950ebcc3dac 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -55,6 +55,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { // Only returns pointers to the slices, as that's all we need // to drop them. May only be called if `self.remaining != 0`. pub(super) unsafe fn as_slices(&self) -> (*mut [T], *mut [T]) { + // SAFETY: Untriaged. unsafe { let deque = self.deque.as_ref(); @@ -98,6 +99,7 @@ impl Drop for Drain<'_, T, A> { let guard = DropGuard(self); if mem::needs_drop::() && guard.0.remaining != 0 { + // SAFETY: Untriaged. unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = guard.0.as_slices(); @@ -115,6 +117,7 @@ impl Drop for Drain<'_, T, A> { #[inline] fn drop(&mut self) { if mem::needs_drop::() && self.0.remaining != 0 { + // SAFETY: Untriaged. unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = self.0.as_slices(); @@ -123,6 +126,7 @@ impl Drop for Drain<'_, T, A> { } } + // SAFETY: Untriaged. let source_deque = unsafe { self.0.deque.as_mut() }; let drain_len = self.0.drain_len; @@ -212,6 +216,7 @@ impl Drop for Drain<'_, T, A> { len = tail_len; }; + // SAFETY: Untriaged. unsafe { source_deque.wrap_copy(src, dst, len); } @@ -241,9 +246,11 @@ impl Iterator for Drain<'_, T, A> { if self.remaining == 0 { return None; } + // SAFETY: Untriaged. let wrapped_idx = unsafe { self.deque.as_ref().to_wrapped_index(self.idx) }; self.idx += 1; self.remaining -= 1; + // SAFETY: Untriaged. Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) }) } @@ -263,7 +270,9 @@ impl DoubleEndedIterator for Drain<'_, T, A> { } self.remaining -= 1; let wrapped_idx = +// SAFETY: Untriaged. unsafe { self.deque.as_ref().to_wrapped_index(self.idx + self.remaining) }; + // SAFETY: Untriaged. Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) }) } } diff --git a/library/alloc/src/collections/vec_deque/extract_if.rs b/library/alloc/src/collections/vec_deque/extract_if.rs index 19439dfb4f05d..3d178d07e1055 100644 --- a/library/alloc/src/collections/vec_deque/extract_if.rs +++ b/library/alloc/src/collections/vec_deque/extract_if.rs @@ -84,6 +84,7 @@ where // Note: we can't use `vec.get_mut(i).unwrap()` here since the precondition for that // function is that i < vec.len, but we've set vec's length to zero. let idx = self.vec.to_wrapped_index(i); + // SAFETY: Untriaged. let cur = unsafe { &mut *self.vec.ptr().add(idx.as_index()) }; let drained = (self.pred)(cur); // Update the index *after* the predicate is called. If the index diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index d3dbd10c863fb..14ab2393ea1b5 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -147,6 +147,7 @@ impl<'a, T> Iterator for Iter<'a, T> { unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { // Safety: The TrustedRandomAccess contract requires that callers only pass an index // that is in bounds. + // SAFETY: Untriaged. unsafe { let i1_len = self.i1.len(); if idx < i1_len { diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 0c5f06e752b7b..cf29810ecb7b3 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -211,6 +211,7 @@ impl<'a, T> Iterator for IterMut<'a, T> { unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { // Safety: The TrustedRandomAccess contract requires that callers only pass an index // that is in bounds. + // SAFETY: Untriaged. unsafe { let i1_len = self.i1.len(); if idx < i1_len { diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 940fce7377938..80127ca36e1dc 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -139,6 +139,7 @@ struct Dropper<'a, T>(&'a mut [T]); impl Drop for Dropper<'_, T> { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(self.0); } @@ -149,6 +150,7 @@ impl Drop for Dropper<'_, T> { unsafe impl<#[may_dangle] T, A: Allocator> Drop for VecDeque { fn drop(&mut self) { let (front, back) = self.as_mut_slices(); + // SAFETY: Untriaged. unsafe { let _back_dropper = Dropper(back); // use drop for [T] @@ -206,6 +208,7 @@ impl VecDeque { /// Moves an element out of the buffer #[inline] unsafe fn buffer_read(&mut self, off: WrappedIndex) -> T { + // SAFETY: Untriaged. unsafe { ptr::read(self.ptr().add(off.as_index())) } } @@ -215,6 +218,7 @@ impl VecDeque { /// May only be called if `off < self.capacity()`. #[inline] unsafe fn buffer_write(&mut self, off: WrappedIndex, value: T) -> &mut T { + // SAFETY: Untriaged. unsafe { let ptr = self.ptr().add(off.as_index()); ptr::write(ptr, value); @@ -226,6 +230,7 @@ impl VecDeque { /// `range` must lie inside `0..self.capacity()`. #[inline] unsafe fn buffer_range(&self, range: Range) -> *mut [T] { + // SAFETY: Untriaged. unsafe { self.ptr().add(range.start).cast_slice(range.end - range.start) } } @@ -304,6 +309,7 @@ impl VecDeque { self.capacity(), ); + // SAFETY: Untriaged. unsafe { let ptr = self.ptr(); let src_ptr = ptr.add(wrapped_src.as_index()); @@ -348,6 +354,7 @@ impl VecDeque { len, self.capacity() ); + // SAFETY: Untriaged. unsafe { ptr::copy(self.ptr().add(src.as_index()), self.ptr().add(dst.as_index()), len); } @@ -372,6 +379,7 @@ impl VecDeque { len, self.capacity() ); + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping( self.ptr().add(src.as_index()), @@ -416,6 +424,7 @@ impl VecDeque { // 2 [_ _ A A A A B B _] // D . . . // + // SAFETY: Untriaged. unsafe { self.copy(src, dst, len); } @@ -429,6 +438,7 @@ impl VecDeque { // 3 [B B B B _ _ _ A A] // . . D . // + // SAFETY: Untriaged. unsafe { self.copy(src, dst, dst_pre_wrap_len); self.copy( @@ -447,6 +457,7 @@ impl VecDeque { // 3 [B B _ _ _ A A A A] // . . D . // + // SAFETY: Untriaged. unsafe { self.copy( src.add(dst_pre_wrap_len), @@ -465,6 +476,7 @@ impl VecDeque { // 3 [C C _ _ _ B B C C] // D . . . // + // SAFETY: Untriaged. unsafe { self.copy(src, dst, src_pre_wrap_len); self.copy( @@ -483,6 +495,7 @@ impl VecDeque { // 3 [C C A A _ _ _ C C] // D . . . // + // SAFETY: Untriaged. unsafe { self.copy( WrappedIndex::zero(), @@ -504,6 +517,7 @@ impl VecDeque { // debug_assert!(dst_pre_wrap_len > src_pre_wrap_len); let delta = dst_pre_wrap_len - src_pre_wrap_len; + // SAFETY: Untriaged. unsafe { self.copy(src, dst, src_pre_wrap_len); self.copy(WrappedIndex::zero(), dst.add(src_pre_wrap_len), delta); @@ -526,6 +540,7 @@ impl VecDeque { // debug_assert!(src_pre_wrap_len > dst_pre_wrap_len); let delta = src_pre_wrap_len - dst_pre_wrap_len; + // SAFETY: Untriaged. unsafe { self.copy( WrappedIndex::zero(), @@ -550,11 +565,13 @@ impl VecDeque { debug_assert!(src.len() <= self.capacity()); let head_room = self.capacity() - dst.as_index(); if src.len() <= head_room { + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(src.as_ptr(), self.ptr().add(dst.as_index()), src.len()); } } else { let (left, right) = src.split_at(head_room); + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(left.as_ptr(), self.ptr().add(dst.as_index()), left.len()); ptr::copy_nonoverlapping(right.as_ptr(), self.ptr(), right.len()); @@ -572,6 +589,7 @@ impl VecDeque { /// See [`ptr::copy_nonoverlapping`]. unsafe fn copy_nonoverlapping_reversed(src: *const T, dst: *mut T, count: usize) { for i in 0..count { + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(src.add(count - 1 - i), dst.add(i), 1) }; } } @@ -579,6 +597,7 @@ impl VecDeque { debug_assert!(src.len() <= self.capacity()); let head_room = self.capacity() - dst.as_index(); if src.len() <= head_room { + // SAFETY: Untriaged. unsafe { copy_nonoverlapping_reversed( src.as_ptr(), @@ -588,6 +607,7 @@ impl VecDeque { } } else { let (left, right) = src.split_at(src.len() - head_room); + // SAFETY: Untriaged. unsafe { copy_nonoverlapping_reversed( right.as_ptr(), @@ -612,6 +632,7 @@ impl VecDeque { iter: impl Iterator, written: &mut usize, ) { + // SAFETY: Untriaged. iter.enumerate().for_each(|(i, element)| unsafe { self.buffer_write(dst.add(i), element); *written += 1; @@ -648,8 +669,10 @@ impl VecDeque { let mut guard = Guard { deque: self, written: 0 }; if head_room >= len { + // SAFETY: Untriaged. unsafe { guard.deque.write_iter(dst, iter, &mut guard.written) }; } else { + // SAFETY: Untriaged. unsafe { guard.deque.write_iter( dst, @@ -697,6 +720,7 @@ impl VecDeque { let tail_len = self.len - head_len; if head_len > tail_len && new_capacity - old_capacity >= tail_len { // B + // SAFETY: Untriaged. unsafe { self.copy_nonoverlapping( WrappedIndex::zero(), @@ -707,6 +731,7 @@ impl VecDeque { } else { // C let new_head = WrappedIndex::from_arbitrary_number(new_capacity - head_len); + // SAFETY: Untriaged. unsafe { // can't use copy_nonoverlapping here, because if e.g. head_len = 2 // and new_capacity = old_capacity + 1, then the heads overlap. @@ -966,6 +991,7 @@ impl VecDeque { pub fn get(&self, index: usize) -> Option<&T> { if index < self.len { let idx = self.to_wrapped_index(index); + // SAFETY: Untriaged. unsafe { Some(&*self.ptr().add(idx.as_index())) } } else { None @@ -996,6 +1022,7 @@ impl VecDeque { pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { if index < self.len { let idx = self.to_wrapped_index(index); + // SAFETY: Untriaged. unsafe { Some(&mut *self.ptr().add(idx.as_index())) } } else { None @@ -1031,6 +1058,7 @@ impl VecDeque { assert!(j < self.len()); let ri = self.to_wrapped_index(i); let rj = self.to_wrapped_index(j); + // SAFETY: Untriaged. unsafe { ptr::swap(self.ptr().add(ri.as_index()), self.ptr().add(rj.as_index())) } } @@ -1080,6 +1108,7 @@ impl VecDeque { if new_cap > old_cap { self.buf.reserve_exact(self.len, additional); + // SAFETY: Untriaged. unsafe { self.handle_capacity_increase(old_cap); } @@ -1112,6 +1141,7 @@ impl VecDeque { // we don't need to reserve_exact(), as the size doesn't have // to be a power of 2. self.buf.reserve(self.len, additional); + // SAFETY: Untriaged. unsafe { self.handle_capacity_increase(old_cap); } @@ -1163,6 +1193,7 @@ impl VecDeque { if new_cap > old_cap { self.buf.try_reserve_exact(self.len, additional)?; + // SAFETY: Untriaged. unsafe { self.handle_capacity_increase(old_cap); } @@ -1211,6 +1242,7 @@ impl VecDeque { if new_cap > old_cap { self.buf.try_reserve(self.len, additional)?; + // SAFETY: Untriaged. unsafe { self.handle_capacity_increase(old_cap); } @@ -1292,6 +1324,7 @@ impl VecDeque { // [. . . . . . . . o o o o o o o . ] // H L // [o o o o o o o . ] + // SAFETY: Untriaged. unsafe { // nonoverlapping because `self.head >= target_cap >= self.len`. self.copy_nonoverlapping(self.head, WrappedIndex::zero(), self.len); @@ -1310,6 +1343,7 @@ impl VecDeque { // [o o . o o o o o ] let len = self.head + self.len - target_cap; // Safety: head is < target_cap, so the index is wrapped + // SAFETY: Untriaged. unsafe { self.copy_nonoverlapping( WrappedIndex::from_arbitrary_number(target_cap), @@ -1332,6 +1366,7 @@ impl VecDeque { // head_len is at least one, so new_head will be < target_cap let new_head = WrappedIndex::from_arbitrary_number(target_cap - head_len); + // SAFETY: Untriaged. unsafe { // can't use `copy_nonoverlapping()` here because the new and old // regions for the head might overlap. @@ -1349,6 +1384,7 @@ impl VecDeque { impl Drop for Guard<'_, T, A> { #[cold] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { // SAFETY: This is only called if `buf.shrink_to_fit` unwinds, // which is the only time it's safe to call `abort_shrink`. @@ -1391,6 +1427,7 @@ impl VecDeque { // There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`), // and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`). + // SAFETY: Untriaged. unsafe { // The old tail and the new tail can't overlap because the head slice lies between them. The // head slice ends at `target_cap`, so that's where we copy to. @@ -1403,6 +1440,7 @@ impl VecDeque { } else { // Either there's not enough spare capacity to make the deque contiguous, or the head is shorter than the tail // (and therefore hopefully cheaper to copy). + // SAFETY: Untriaged. unsafe { // The old and the new head slice can overlap, so we can't use `copy_nonoverlapping` here. self.copy(self.head, old_head, head_len); @@ -1440,6 +1478,7 @@ impl VecDeque { // `begin <= back.len()` in the first case // * The head of the VecDeque is moved before calling `drop_in_place`, // so no value is dropped twice if `drop_in_place` panics + // SAFETY: Untriaged. unsafe { if len >= self.len { return; @@ -1487,6 +1526,7 @@ impl VecDeque { #[doc(alias = "truncate_front")] #[stable(feature = "vec_deque_truncate_front", since = "CURRENT_RUSTC_VERSION")] pub fn retain_back(&mut self, len: usize) { + // SAFETY: Untriaged. unsafe { if len >= self.len { // No action is taken @@ -1565,6 +1605,7 @@ impl VecDeque { let fptr = front.as_mut_ptr(); let bptr = back.as_mut_ptr(); + // SAFETY: Untriaged. unsafe { let (drop_a, drop_b, drop_c) = if end <= flen { // Kept range lies in `front`. The dropped suffix is the rest of `front` @@ -1859,6 +1900,7 @@ impl VecDeque { // it's ok to pass them to `buffer_range` and // dereference the result. let a = unsafe { &*self.buffer_range(a_range) }; + // SAFETY: Untriaged. let b = unsafe { &*self.buffer_range(b_range) }; Iter::new(a.iter(), b.iter()) } @@ -1899,6 +1941,7 @@ impl VecDeque { // it's ok to pass them to `buffer_range` and // dereference the result. let a = unsafe { &mut *self.buffer_range(a_range) }; + // SAFETY: Untriaged. let b = unsafe { &mut *self.buffer_range(b_range) }; IterMut::new(a.iter_mut(), b.iter_mut()) } @@ -1975,6 +2018,7 @@ impl VecDeque { // "forget" about the values after the start of the drain until after // the drain is complete and the Drain destructor is run. + // SAFETY: Untriaged. unsafe { Drain::new(self, drain_start, drain_len) } } @@ -2201,6 +2245,7 @@ impl VecDeque { let old_head = self.head; self.head = self.to_wrapped_index(1); self.len -= 1; + // SAFETY: Untriaged. unsafe { core::hint::assert_unchecked(self.len < self.capacity()); Some(self.buffer_read(old_head)) @@ -2228,6 +2273,7 @@ impl VecDeque { None } else { self.len -= 1; + // SAFETY: Untriaged. unsafe { core::hint::assert_unchecked(self.len < self.capacity()); Some(self.buffer_read(self.to_wrapped_index(self.len))) @@ -2360,6 +2406,7 @@ impl VecDeque { let len = self.len; self.len += 1; + // SAFETY: Untriaged. unsafe { self.buffer_write(self.to_wrapped_index(len), value) } } @@ -2572,6 +2619,7 @@ impl VecDeque { // `index + 1` can't overflow, because if index was usize::MAX, then either the // assert would've failed, or the deque would've tried to grow past usize::MAX // and panicked. + // SAFETY: Untriaged. unsafe { // see `remove()` for explanation why this wrap_copy() call is safe. self.wrap_copy(self.to_wrapped_index(index), self.to_wrapped_index(index + 1), k); @@ -2581,6 +2629,7 @@ impl VecDeque { } else { let old_head = self.head; self.head = self.wrap_sub(self.head, 1); + // SAFETY: Untriaged. unsafe { self.wrap_copy(old_head, self.head, index); self.len += 1; @@ -2619,6 +2668,7 @@ impl VecDeque { let wrapped_idx = self.to_wrapped_index(index); + // SAFETY: Untriaged. let elem = unsafe { Some(self.buffer_read(wrapped_idx)) }; let k = self.len - index - 1; @@ -2626,11 +2676,13 @@ impl VecDeque { // its length argument will be at most `self.len / 2`, so there can't be more than // one overlapping area. if k < index { + // SAFETY: Untriaged. unsafe { self.wrap_copy(self.wrap_add(wrapped_idx, 1), wrapped_idx, k) }; self.len -= 1; } else { let old_head = self.head; self.head = self.to_wrapped_index(1); + // SAFETY: Untriaged. unsafe { self.wrap_copy(old_head, self.head, index) }; self.len -= 1; } @@ -2678,6 +2730,7 @@ impl VecDeque { let first_len = first_half.len(); let second_len = second_half.len(); + // SAFETY: Untriaged. unsafe { if at < first_len { // `at` lies in the first half. @@ -2739,6 +2792,7 @@ impl VecDeque { } self.reserve(other.len); + // SAFETY: Untriaged. unsafe { let (left, right) = other.as_slices(); self.copy_slice(self.to_wrapped_index(self.len), left); @@ -2858,6 +2912,7 @@ impl VecDeque { debug_assert!(self.is_full()); let old_cap = self.capacity(); self.buf.grow_one(); + // SAFETY: Untriaged. unsafe { self.handle_capacity_increase(old_cap); } @@ -2962,6 +3017,7 @@ impl VecDeque { } if self.is_contiguous() { + // SAFETY: Untriaged. unsafe { return slice::from_raw_parts_mut(self.ptr().add(self.head.as_index()), self.len); } @@ -2987,6 +3043,7 @@ impl VecDeque { // // from: DEFGH....ABC // to: ABCDEFGH.... + // SAFETY: Untriaged. unsafe { self.copy( WrappedIndex::zero(), @@ -3006,6 +3063,7 @@ impl VecDeque { // // from: FGH....ABCDE // to: ...ABCDEFGH. + // SAFETY: Untriaged. unsafe { self.copy(head, tail, head_len); // FGHABCDE.... @@ -3038,6 +3096,7 @@ impl VecDeque { // 2. rotate used part of the buffer // 3. update head to point to the new beginning (which is just `free`) + // SAFETY: Untriaged. unsafe { // if there is no free space in the buffer, then the slices are already // right next to each other and we don't need to move any memory. @@ -3070,6 +3129,7 @@ impl VecDeque { // 2. rotate used part of the buffer // 3. update head to point to the new beginning (which is the beginning of the buffer) + // SAFETY: Untriaged. unsafe { // if there is no free space in the buffer, then the slices are already // right next to each other and we don't need to move any memory. @@ -3097,6 +3157,7 @@ impl VecDeque { } } + // SAFETY: Untriaged. unsafe { slice::from_raw_parts_mut(ptr.add(self.head.as_index()), self.len) } } @@ -3137,8 +3198,10 @@ impl VecDeque { assert!(n <= self.len()); let k = self.len - n; if n <= k { + // SAFETY: Untriaged. unsafe { self.rotate_left_inner(n) } } else { + // SAFETY: Untriaged. unsafe { self.rotate_right_inner(k) } } } @@ -3180,8 +3243,10 @@ impl VecDeque { assert!(n <= self.len()); let k = self.len - n; if n <= k { + // SAFETY: Untriaged. unsafe { self.rotate_right_inner(n) } } else { + // SAFETY: Untriaged. unsafe { self.rotate_left_inner(k) } } } @@ -3196,6 +3261,7 @@ impl VecDeque { unsafe fn rotate_left_inner(&mut self, mid: usize) { debug_assert!(mid * 2 <= self.len()); + // SAFETY: Untriaged. unsafe { self.wrap_copy(self.head, self.to_wrapped_index(self.len), mid); } @@ -3205,6 +3271,7 @@ impl VecDeque { unsafe fn rotate_right_inner(&mut self, k: usize) { debug_assert!(k * 2 <= self.len()); self.head = self.wrap_sub(self.head, k); + // SAFETY: Untriaged. unsafe { self.wrap_copy(self.to_wrapped_index(self.len), self.head, k); } @@ -3566,6 +3633,7 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; + // SAFETY: Untriaged. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3592,6 +3660,7 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); let cap = self.capacity(); + // SAFETY: Untriaged. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3643,6 +3712,7 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; + // SAFETY: Untriaged. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3665,6 +3735,7 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); + // SAFETY: Untriaged. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3995,6 +4066,7 @@ impl From> for VecDeque { Self { head: WrappedIndex::zero(), len, + // SAFETY: Untriaged. buf: unsafe { RawVec::from_raw_parts_in(ptr, cap, alloc) }, } } @@ -4034,6 +4106,7 @@ impl From> for Vec { fn from(mut other: VecDeque) -> Self { other.make_contiguous(); + // SAFETY: Untriaged. unsafe { let other = ManuallyDrop::new(other); let buf = other.buf.ptr(); diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index 0699d403d9de5..31997f187dec2 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -57,6 +57,7 @@ where ); self.reserve(additional); + // SAFETY: Untriaged. let written = unsafe { self.write_iter_wrapping(self.to_wrapped_index(self.len), iter, additional) }; @@ -82,6 +83,7 @@ impl SpecExtend> for Ve let slice = iterator.as_slice(); self.reserve(slice.len()); + // SAFETY: Untriaged. unsafe { self.copy_slice(self.to_wrapped_index(self.len), slice); self.len += slice.len(); @@ -108,6 +110,7 @@ where let slice = iterator.as_slice(); self.reserve(slice.len()); + // SAFETY: Untriaged. unsafe { self.copy_slice(self.to_wrapped_index(self.len), slice); self.len += slice.len(); @@ -213,6 +216,7 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront> f } self.reserve(iter.remaining); + // SAFETY: Untriaged. unsafe { // SAFETY: iter.remaining != 0. let (left, right) = iter.as_slices(); @@ -240,6 +244,7 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront SpecExtendFront(deque: &mut VecDeque, slice: &[T]) { + // SAFETY: Untriaged. unsafe { deque.head = deque.wrap_sub(deque.head, slice.len()); deque.copy_slice(deque.head, slice); @@ -276,6 +282,7 @@ unsafe fn prepend(deque: &mut VecDeque, slice: &[T]) { /// - `deque` must have space for `slice.len()` new elements. /// - Elements of `slice` will be copied into the deque, make sure to forget the elements if `T` is not `Copy`. unsafe fn prepend_reversed(deque: &mut VecDeque, slice: &[T]) { + // SAFETY: Untriaged. unsafe { deque.head = deque.wrap_sub(deque.head, slice.len()); deque.copy_slice_reversed(deque.head, slice); diff --git a/library/alloc/src/collections/vec_deque/splice.rs b/library/alloc/src/collections/vec_deque/splice.rs index a29e9c3742564..bdbb61afafe94 100644 --- a/library/alloc/src/collections/vec_deque/splice.rs +++ b/library/alloc/src/collections/vec_deque/splice.rs @@ -64,6 +64,7 @@ impl Drop for Splice<'_, I, A> { // At this point draining is done and the only remaining tasks are splicing // and moving things into the final place. + // SAFETY: Untriaged. unsafe { let tail_len = self.drain.tail_len; // #elements behind the drain @@ -114,6 +115,7 @@ impl Drain<'_, T, A> { /// self.deque must be valid. self.deque.len and self.deque.len + self.drain_len must be less /// than twice the deque's capacity. unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + // SAFETY: Untriaged. let deque = unsafe { self.deque.as_mut() }; let range_start = deque.len; let range_end = range_start + self.drain_len; @@ -121,6 +123,7 @@ impl Drain<'_, T, A> { for idx in range_start..range_end { if let Some(new_item) = replace_with.next() { let index = deque.to_wrapped_index(idx); + // SAFETY: Untriaged. unsafe { deque.buffer_write(index, new_item) }; deque.len += 1; self.drain_len -= 1; @@ -137,6 +140,7 @@ impl Drain<'_, T, A> { /// /// self.deque must be valid. unsafe fn move_tail(&mut self, additional: usize) { + // SAFETY: Untriaged. let deque = unsafe { self.deque.as_mut() }; // `Drain::new` modifies the deque's len (so does `Drain::fill` here) @@ -182,6 +186,7 @@ impl Drain<'_, T, A> { } let new_tail_start = tail_start + additional; + // SAFETY: Untriaged. unsafe { deque.wrap_copy( deque.to_wrapped_index(tail_start), diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index b340cf9566f2e..53e89235f2f5a 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -264,6 +264,7 @@ impl CString { let bytes: Vec = self.into(); match memchr::memchr(0, &bytes) { Some(i) => Err(NulError(i, bytes)), + // SAFETY: Untriaged. None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }), } } @@ -287,6 +288,7 @@ impl CString { // This allows better optimizations if lto enabled. match memchr::memchr(0, bytes) { Some(i) => Err(NulError(i, buffer)), + // SAFETY: Untriaged. None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }), } } @@ -339,6 +341,7 @@ impl CString { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_vec_unchecked(v: Vec) -> Self { debug_assert!(memchr::memchr(0, &v).is_none()); + // SAFETY: Untriaged. unsafe { Self::_from_vec_unchecked(v) } } @@ -478,6 +481,7 @@ impl CString { pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { error: e.utf8_error(), + // SAFETY: Untriaged. inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, }) } @@ -584,6 +588,7 @@ impl CString { #[stable(feature = "as_c_str", since = "1.20.0")] #[rustc_diagnostic_item = "cstring_as_c_str"] pub fn as_c_str(&self) -> &CStr { + // SAFETY: Untriaged. unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } @@ -599,6 +604,7 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_boxed_c_str(self) -> Box { + // SAFETY: Untriaged. unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) } } @@ -610,6 +616,7 @@ impl CString { // Then we can return the box directly without invalidating it. // See https://github.com/rust-lang/rust/issues/62553. let this = mem::ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { ptr::read(&this.inner) } } @@ -634,6 +641,7 @@ impl CString { #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len()); + // SAFETY: Untriaged. unsafe { Self::_from_vec_with_nul_unchecked(v) } } @@ -702,6 +710,7 @@ impl CString { impl Drop for CString { #[inline] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { *self.inner.get_unchecked_mut(0) = 0; } @@ -802,6 +811,7 @@ impl From> for CString { #[inline] fn from(s: Box) -> CString { let raw = Box::into_raw(s) as *mut [u8]; + // SAFETY: Untriaged. CString { inner: unsafe { Box::from_raw(raw) } } } } @@ -812,6 +822,7 @@ impl From>> for CString { /// copying nor checking for inner nul bytes. #[inline] fn from(v: Vec>) -> CString { + // SAFETY: Untriaged. unsafe { // Transmute `Vec>` to `Vec`. let v: Vec = { @@ -906,6 +917,7 @@ impl From for Arc { #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); + // SAFETY: Untriaged. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } } } @@ -918,6 +930,7 @@ impl From<&CStr> for Arc { #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); + // SAFETY: Untriaged. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } } } @@ -940,6 +953,7 @@ impl From for Rc { #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); + // SAFETY: Untriaged. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } } } @@ -951,6 +965,7 @@ impl From<&CStr> for Rc { #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); + // SAFETY: Untriaged. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } } } diff --git a/library/alloc/src/io/buf_read.rs b/library/alloc/src/io/buf_read.rs index bba1c2b8c8a45..d496c8c614fbf 100644 --- a/library/alloc/src/io/buf_read.rs +++ b/library/alloc/src/io/buf_read.rs @@ -343,6 +343,7 @@ pub trait BufRead: Read { // Note that we are not calling the `.read_until` method here, but // rather our hardcoded implementation. For more details as to why, see // the comments in `default_read_to_string`. + // SAFETY: Untriaged. unsafe { append_to_string(buf, |b| default_read_until(self, b'\n', b)) } } diff --git a/library/alloc/src/io/buffered/bufreader.rs b/library/alloc/src/io/buffered/bufreader.rs index e8b3302e29b98..ef3fe29330d87 100644 --- a/library/alloc/src/io/buffered/bufreader.rs +++ b/library/alloc/src/io/buffered/bufreader.rs @@ -456,6 +456,7 @@ impl Read for BufReader { // bytes but also modify existing bytes and render them invalid. On the other hand, // if `buf` is empty then by definition any writes must be appends and // `append_to_string` will validate all of the new bytes. + // SAFETY: Untriaged. unsafe { crate::io::append_to_string(buf, |b| self.read_to_end(b)) } } else { // We cannot append our byte buffer directly onto the `buf` String as there could diff --git a/library/alloc/src/io/buffered/bufwriter.rs b/library/alloc/src/io/buffered/bufwriter.rs index 806e71c2772ae..6a7d8c762dac7 100644 --- a/library/alloc/src/io/buffered/bufwriter.rs +++ b/library/alloc/src/io/buffered/bufwriter.rs @@ -470,6 +470,7 @@ impl BufWriter { let old_len = self.buf.len(); let buf_len = buf.len(); let src = buf.as_ptr(); + // SAFETY: Untriaged. unsafe { let dst = self.buf.as_mut_ptr().add(old_len); ptr::copy_nonoverlapping(src, dst, buf_len); diff --git a/library/alloc/src/io/cursor.rs b/library/alloc/src/io/cursor.rs index 4bd5a59e54fad..df01104b1f733 100644 --- a/library/alloc/src/io/cursor.rs +++ b/library/alloc/src/io/cursor.rs @@ -157,6 +157,7 @@ fn reserve_and_pad( debug_assert!(spare.len() >= diff); // Safety: we have allocated enough capacity for this. // And we are only writing, not reading + // SAFETY: Untriaged. unsafe { spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0)); vec.set_len(pos); @@ -176,6 +177,7 @@ where A: Allocator, { debug_assert!(vec.capacity() >= pos + buf.len()); + // SAFETY: Untriaged. unsafe { vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()) }; pos + buf.len() } @@ -201,6 +203,7 @@ where // Write the buf then progress the vec forward if necessary // Safety: we have ensured that the capacity is available // and that all bytes get written up to pos + // SAFETY: Untriaged. unsafe { pos = vec_write_all_unchecked(pos, vec, buf); if pos > vec.len() { @@ -240,6 +243,7 @@ where // Write the buf then progress the vec forward if necessary // Safety: we have ensured that the capacity is available // and that all bytes get written up to the last pos + // SAFETY: Untriaged. unsafe { for buf in bufs { pos = vec_write_all_unchecked(pos, vec, buf); diff --git a/library/alloc/src/io/error.rs b/library/alloc/src/io/error.rs index 055d743dee6a1..7813b26bc460b 100644 --- a/library/alloc/src/io/error.rs +++ b/library/alloc/src/io/error.rs @@ -216,6 +216,7 @@ impl Error { Ok(*err) } else { // Safety: We have just checked that the condition is true + // SAFETY: Untriaged. unsafe { core::hint::unreachable_unchecked() } } } else { @@ -256,6 +257,7 @@ fn custom_owner_from_box( unsafe fn drop_box_raw(ptr: *mut T) { // SAFETY // Caller ensures `ptr` is valid to pass into `Box::from_raw`. + // SAFETY: Untriaged. drop(unsafe { Box::from_raw(ptr) }) } diff --git a/library/alloc/src/io/read.rs b/library/alloc/src/io/read.rs index e3d26218c09a0..4a9e15e5c4094 100644 --- a/library/alloc/src/io/read.rs +++ b/library/alloc/src/io/read.rs @@ -632,6 +632,7 @@ pub trait Read { self.read_buf_exact(borrowed_buf.unfilled())?; // Guard against incorrect `read_buf_exact` implementations. assert_eq!(borrowed_buf.len(), N); + // SAFETY: Untriaged. Ok(unsafe { MaybeUninit::array_assume_init(buf) }) } @@ -806,6 +807,7 @@ where let len_original = buf.len(); // SAFETY: invalid UTF-8 discarded before return or unwind let buf_vec = unsafe { buf.as_mut_vec() }; + // SAFETY: Untriaged. let mut g = DropGuard::new((len_original, buf_vec), |(len, buf)| unsafe { buf.set_len(len); }); @@ -1010,6 +1012,7 @@ pub fn default_read_to_string( // To prevent extraneously checking the UTF-8-ness of the entire buffer // we pass it to our hardcoded `default_read_to_end` implementation which // we know is guaranteed to only read data into the end of the buffer. + // SAFETY: Untriaged. unsafe { append_to_string(buf, |b| default_read_to_end(r, b, size_hint)) } } diff --git a/library/alloc/src/io/util.rs b/library/alloc/src/io/util.rs index 9bf5a56dd7157..0fd55a7eaab87 100644 --- a/library/alloc/src/io/util.rs +++ b/library/alloc/src/io/util.rs @@ -287,6 +287,7 @@ impl Read for Take { unsafe { buf.set_init() }; } + // SAFETY: Untriaged. unsafe { // SAFETY: filled bytes have been filled buf.advance(filled); diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 5d4ad3ac4bf98..d0fa74f7f9ee0 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -38,12 +38,14 @@ enum AllocInit { type Cap = core::num::niche_types::UsizeNoHighBit; +// SAFETY: Untriaged. const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) }; /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. /// /// # Safety: cap must be <= `isize::MAX`. const unsafe fn new_cap(cap: usize) -> Cap { + // SAFETY: Untriaged. if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } } } @@ -243,6 +245,7 @@ impl RawVec { ); let me = ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { let slice = me.ptr().cast::>().cast_slice(len); Box::from_raw_in(slice, ptr::read(&me.inner.alloc)) @@ -413,6 +416,7 @@ impl RawVec { /// Panics if the given amount is *larger* than the current capacity. #[inline] pub(crate) fn try_shrink_to_fit(&mut self, cap: usize) -> Result<(), TryReserveError> { + // SAFETY: Untriaged. unsafe { self.inner.try_shrink_to_fit(cap, T::LAYOUT) } } } @@ -434,6 +438,7 @@ const impl RawVecInner { fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { Ok(this) => { +// SAFETY: Untriaged. unsafe { // Make it more obvious that a subsequent Vec::reserve(capacity) will not allocate. hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); @@ -477,6 +482,7 @@ const impl RawVecInner { // here should change to `ptr.len() / size_of::()`. Ok(Self { ptr: Unique::from(ptr.cast()), +// SAFETY: Untriaged. cap: unsafe { Cap::new_unchecked(capacity) }, alloc, }) @@ -548,9 +554,11 @@ const impl RawVecInner { ) -> Result, TryReserveError> { let new_layout = layout_array(cap, elem_layout)?; +// SAFETY: Untriaged. let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } { // FIXME(const-hack): switch to `debug_assert_eq` debug_assert!(old_layout.align() == new_layout.align()); +// SAFETY: Untriaged. unsafe { // The allocator checks for alignment equality hint::assert_unchecked(old_layout.align() == new_layout.align()); @@ -592,6 +600,7 @@ impl RawVecInner { #[inline] const unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self { + // SAFETY: Untriaged. Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } } @@ -635,6 +644,7 @@ impl RawVecInner { // and could hypothetically handle differences between stride and size, but this memory // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. + // SAFETY: Untriaged. unsafe { let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); @@ -668,6 +678,7 @@ impl RawVecInner { } if self.needs_to_grow(len, additional, elem_layout) { + // SAFETY: Untriaged. unsafe { do_reserve_and_handle(self, len, additional, elem_layout); } @@ -690,6 +701,7 @@ impl RawVecInner { self.grow_amortized(len, additional, elem_layout)?; } } + // SAFETY: Untriaged. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -725,6 +737,7 @@ impl RawVecInner { self.grow_exact(len, additional, elem_layout)?; } } + // SAFETY: Untriaged. unsafe { // Inform the optimizer that the reservation has succeeded or wasn't needed hint::assert_unchecked(!self.needs_to_grow(len, additional, elem_layout)); @@ -740,6 +753,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] unsafe fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) { + // SAFETY: Untriaged. if let Err(err) = unsafe { self.shrink(cap, elem_layout) } { handle_error(err); } @@ -756,6 +770,7 @@ impl RawVecInner { cap: usize, elem_layout: Layout, ) -> Result<(), TryReserveError> { + // SAFETY: Untriaged. unsafe { self.shrink(cap, elem_layout) } } @@ -771,6 +786,7 @@ impl RawVecInner { // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / size_of::()`. self.ptr = Unique::from(ptr.cast()); + // SAFETY: Untriaged. self.cap = unsafe { Cap::new_unchecked(cap) }; } @@ -837,11 +853,14 @@ impl RawVecInner { // for the T::IS_ZST case since current_memory() will have returned // None. if cap == 0 { + // SAFETY: Untriaged. unsafe { self.alloc.deallocate(ptr, layout) }; self.ptr = +// SAFETY: Untriaged. unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; self.cap = ZERO_CAP; } else { + // SAFETY: Untriaged. let ptr = unsafe { // Layout cannot overflow here because it would have // overflowed earlier when capacity was larger. @@ -872,6 +891,7 @@ const impl RawVecInner { unsafe fn deallocate(&mut self, elem_layout: Layout) { // SAFETY: Precondition passed to caller if let Some((ptr, layout)) = unsafe { self.current_memory(elem_layout) } { + // SAFETY: Untriaged. unsafe { self.alloc.deallocate(ptr, layout); } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 38ba8d64f900e..7a55dea57af9d 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -359,11 +359,13 @@ unsafe impl CloneFromCell for Rc {} impl Rc { #[inline] unsafe fn from_inner(ptr: NonNull>) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner_in(ptr, Global) } } #[inline] unsafe fn from_ptr(ptr: *mut RcInner) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } } } @@ -373,12 +375,14 @@ impl Rc { fn inner(&self) -> &RcInner { // This unsafety is ok because while this Rc is alive we're guaranteed // that the inner pointer is valid. + // SAFETY: Untriaged. unsafe { self.ptr.as_ref() } } #[inline] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); + // SAFETY: Untriaged. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -389,6 +393,7 @@ impl Rc { #[inline] unsafe fn from_ptr_in(ptr: *mut RcInner, alloc: A) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } } @@ -402,6 +407,7 @@ impl Rc { // Destroy the contained object. // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).value); } @@ -425,6 +431,7 @@ impl Rc { // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. + // SAFETY: Untriaged. unsafe { Self::from_inner( Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value })) @@ -513,6 +520,7 @@ impl Rc { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit() -> Rc> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr(Rc::allocate_for_layout( Layout::new::(), @@ -544,6 +552,7 @@ impl Rc { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed() -> Rc> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr(Rc::allocate_for_layout( Layout::new::(), @@ -570,6 +579,7 @@ impl Rc { // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. + // SAFETY: Untriaged. unsafe { Ok(Self::from_inner( Box::leak(Box::try_new(RcInner { @@ -603,6 +613,7 @@ impl Rc { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn try_new_uninit() -> Result>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Rc::from_ptr(Rc::try_allocate_for_layout( Layout::new::(), @@ -635,6 +646,7 @@ impl Rc { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] pub fn try_new_zeroed() -> Result>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Rc::from_ptr(Rc::try_allocate_for_layout( Layout::new::(), @@ -649,6 +661,7 @@ impl Rc { #[stable(feature = "pin", since = "1.33.0")] #[must_use] pub fn pin(value: T) -> Pin> { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Rc::new(value)) } } @@ -679,6 +692,7 @@ impl Rc { && align_of::() == align_of::() && Rc::is_unique(&this) { + // SAFETY: Untriaged. unsafe { let ptr = Rc::into_raw(this); let value = ptr.read(); @@ -726,6 +740,7 @@ impl Rc { && align_of::() == align_of::() && Rc::is_unique(&this) { + // SAFETY: Untriaged. unsafe { let ptr = Rc::into_raw(this); let value = ptr.read(); @@ -791,6 +806,7 @@ impl Rc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_in(alloc: A) -> Rc, A> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr_in( Rc::allocate_for_layout( @@ -828,6 +844,7 @@ impl Rc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_in(alloc: A) -> Rc, A> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr_in( Rc::allocate_for_layout( @@ -885,6 +902,7 @@ impl Rc { }, alloc, )); + // SAFETY: Untriaged. let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); let init_ptr: NonNull> = uninit_ptr.cast(); @@ -898,6 +916,7 @@ impl Rc { // otherwise. let data = data_fn(&weak); + // SAFETY: Untriaged. unsafe { let inner = init_ptr.as_ptr(); ptr::write(&raw mut (*inner).value, data); @@ -940,6 +959,7 @@ impl Rc { RcInner { strong: Cell::new(1), weak: Cell::new(1), value }, alloc, )?); + // SAFETY: Untriaged. Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) } @@ -970,6 +990,7 @@ impl Rc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Rc::from_ptr_in( Rc::try_allocate_for_layout( @@ -1008,6 +1029,7 @@ impl Rc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Rc::from_ptr_in( Rc::try_allocate_for_layout( @@ -1029,6 +1051,7 @@ impl Rc { where A: 'static, { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Rc::new_in(value, alloc)) } } @@ -1057,7 +1080,9 @@ impl Rc { if Rc::strong_count(&this) == 1 { let this = ManuallyDrop::new(this); + // SAFETY: Untriaged. let val: T = unsafe { ptr::read(&**this) }; // copy the contained object + // SAFETY: Untriaged. let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator // Indicate to Weaks that they can't be promoted by decrementing @@ -1133,6 +1158,7 @@ impl Rc<[T]> { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) } } @@ -1158,6 +1184,7 @@ impl Rc<[T]> { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr(Rc::allocate_for_layout( Layout::array::(len).unwrap(), @@ -1197,6 +1224,7 @@ impl Rc<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr_in(Rc::allocate_for_slice_in(len, &alloc), alloc) } } @@ -1225,6 +1253,7 @@ impl Rc<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { Rc::from_ptr_in( Rc::allocate_for_layout( @@ -1303,6 +1332,7 @@ impl Rc, A> { #[inline] pub unsafe fn assume_init(self) -> Rc { let (ptr, alloc) = Rc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { Rc::from_inner_in(ptr.cast(), alloc) } } } @@ -1364,6 +1394,7 @@ impl Rc { let mut in_progress: UniqueRcUninit = UniqueRcUninit::new(value, alloc); // Initialize with clone of value. + // SAFETY: Untriaged. unsafe { // Clone. If the clone panics, `in_progress` will be dropped and clean up. value.clone_to_uninit(in_progress.data_ptr().cast()); @@ -1392,6 +1423,7 @@ impl Rc { let mut in_progress: UniqueRcUninit = UniqueRcUninit::try_new(value, alloc)?; // Initialize with clone of value. + // SAFETY: Untriaged. let initialized_clone = unsafe { // Clone. If the clone panics, `in_progress` will be dropped and clean up. value.clone_to_uninit(in_progress.data_ptr().cast()); @@ -1437,6 +1469,7 @@ impl Rc<[mem::MaybeUninit], A> { #[inline] pub unsafe fn assume_init(self) -> Rc<[T], A> { let (ptr, alloc) = Rc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { Rc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -1509,6 +1542,7 @@ impl Rc { #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_raw_in(ptr, Global) } } @@ -1567,6 +1601,7 @@ impl Rc { #[inline] #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] pub unsafe fn increment_strong_count(ptr: *const T) { + // SAFETY: Untriaged. unsafe { Self::increment_strong_count_in(ptr, Global) } } @@ -1604,6 +1639,7 @@ impl Rc { #[inline] #[stable(feature = "rc_mutate_strong_count", since = "1.53.0")] pub unsafe fn decrement_strong_count(ptr: *const T) { + // SAFETY: Untriaged. unsafe { Self::decrement_strong_count_in(ptr, Global) } } } @@ -1644,6 +1680,7 @@ impl Rc { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&this.alloc) }; (ptr, alloc) } @@ -1747,11 +1784,14 @@ impl Rc { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // SAFETY: Untriaged. let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcInner. + // SAFETY: Untriaged. let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner }; + // SAFETY: Untriaged. unsafe { Self::from_ptr_in(rc_ptr, alloc) } } @@ -1855,6 +1895,7 @@ impl Rc { A: Clone, { // Retain Rc, but don't touch refcount by wrapping in ManuallyDrop + // SAFETY: Untriaged. let rc = unsafe { mem::ManuallyDrop::new(Rc::::from_raw_in(ptr, alloc)) }; // Now increase refcount, but don't drop new refcount either let _rc_clone: mem::ManuallyDrop<_> = rc.clone(); @@ -1897,6 +1938,7 @@ impl Rc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { + // SAFETY: Untriaged. unsafe { drop(Rc::from_raw_in(ptr, alloc)) }; } @@ -1934,6 +1976,7 @@ impl Rc { #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { + // SAFETY: Untriaged. if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } } @@ -2002,6 +2045,7 @@ impl Rc { pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { // We are careful to *not* create a reference covering the "count" fields, as // this would conflict with accesses to the reference counts (e.g. by `Weak`). + // SAFETY: Untriaged. unsafe { &mut (*this.ptr.as_ptr()).value } } @@ -2092,6 +2136,7 @@ impl Rc { let mut in_progress: UniqueRcUninit = UniqueRcUninit::new(&**this, this.alloc.clone()); + // SAFETY: Untriaged. unsafe { // Initialize `in_progress` with move of **this. // We have to express this in terms of bytes because `T: ?Sized`; there is no @@ -2123,6 +2168,7 @@ impl Rc { // reference count is guaranteed to be 1 at this point, and we required // the `Rc` itself to be `mut`, so we're returning the only possible // reference to the allocation. + // SAFETY: Untriaged. unsafe { &mut this.ptr.as_mut().value } } } @@ -2186,6 +2232,7 @@ impl Rc { #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Self> { if (*self).is::() { + // SAFETY: Untriaged. unsafe { let (ptr, alloc) = Rc::into_inner_with_allocator(self); Ok(Rc::from_inner_in(ptr.cast(), alloc)) @@ -2224,6 +2271,7 @@ impl Rc { #[inline] #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Rc { + // SAFETY: Untriaged. unsafe { let (ptr, alloc) = Rc::into_inner_with_allocator(self); Rc::from_inner_in(ptr.cast(), alloc) @@ -2244,6 +2292,7 @@ impl Rc { mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner, ) -> *mut RcInner { let layout = rc_inner_layout_for_value_layout(value_layout); + // SAFETY: Untriaged. unsafe { Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rc_inner) .unwrap_or_else(|_| handle_alloc_error(layout)) @@ -2269,6 +2318,7 @@ impl Rc { // Initialize the RcInner let inner = mem_to_rc_inner(ptr.as_non_null_ptr().as_ptr()); + // SAFETY: Untriaged. unsafe { debug_assert_eq!(Layout::for_value_raw(inner), layout); @@ -2285,6 +2335,7 @@ impl Rc { #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcInner { // Allocate for the `RcInner` using the given value. + // SAFETY: Untriaged. unsafe { Rc::::allocate_for_layout( Layout::for_value_raw(ptr), @@ -2296,6 +2347,7 @@ impl Rc { #[cfg(not(no_global_oom_handling))] fn from_box_in(src: Box) -> Rc { + // SAFETY: Untriaged. unsafe { let value_size = size_of_val(&*src); let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); @@ -2321,6 +2373,7 @@ impl Rc<[T]> { /// Allocates an `RcInner<[T]>` with the given length. #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice(len: usize) -> *mut RcInner<[T]> { + // SAFETY: Untriaged. unsafe { Self::allocate_for_layout( Layout::array::(len).unwrap(), @@ -2336,6 +2389,7 @@ impl Rc<[T]> { /// bind `T: TrivialClone`. #[cfg(not(no_global_oom_handling))] unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { + // SAFETY: Untriaged. unsafe { let ptr = Self::allocate_for_slice(v.len()); ptr::copy_nonoverlapping(v.as_ptr(), (&raw mut (*ptr).value) as *mut T, v.len()); @@ -2360,6 +2414,7 @@ impl Rc<[T]> { impl Drop for Guard { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { let slice = from_raw_parts_mut(self.elems, self.n_elems); ptr::drop_in_place(slice); @@ -2369,6 +2424,7 @@ impl Rc<[T]> { } } + // SAFETY: Untriaged. unsafe { let ptr = Self::allocate_for_slice(len); @@ -2398,6 +2454,7 @@ impl Rc<[T], A> { #[inline] #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcInner<[T]> { + // SAFETY: Untriaged. unsafe { Rc::<[T]>::allocate_for_layout( Layout::array::(len).unwrap(), @@ -2418,6 +2475,7 @@ trait RcFromSlice { impl RcFromSlice for Rc<[T]> { #[inline] default fn from_slice(v: &[T]) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } } } @@ -2495,6 +2553,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc { /// ``` #[inline] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { self.inner().dec_strong(); if self.inner().strong() == 0 { @@ -2522,6 +2581,7 @@ impl Clone for Rc { /// ``` #[inline] fn clone(&self) -> Self { + // SAFETY: Untriaged. unsafe { self.inner().inc_strong(); Self::from_inner_in(self.ptr, self.alloc.clone()) @@ -2550,6 +2610,7 @@ impl Default for Rc { /// ``` #[inline] fn default() -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner( Box::leak(Box::write( @@ -2572,6 +2633,7 @@ impl Default for Rc { fn default() -> Self { let rc = Rc::<[u8]>::default(); // `[u8]` has the same layout as `str`. + // SAFETY: Untriaged. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) } } } @@ -2598,6 +2660,7 @@ where { #[inline] fn default() -> Self { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Rc::::default()) } } } @@ -2938,6 +3001,7 @@ impl From<&str> for Rc { #[inline] fn from(v: &str) -> Rc { let rc = Rc::<[u8]>::from(v.as_bytes()); + // SAFETY: Untriaged. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) } } } @@ -3015,6 +3079,7 @@ impl From> for Rc<[T], A> { /// ``` #[inline] fn from(v: Vec) -> Rc<[T], A> { + // SAFETY: Untriaged. unsafe { let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); @@ -3083,6 +3148,7 @@ impl TryFrom> for Rc<[T; N], A> { fn try_from(boxed_slice: Rc<[T], A>) -> Result { if boxed_slice.len() == N { let (ptr, alloc) = Rc::into_inner_with_allocator(boxed_slice); + // SAFETY: Untriaged. Ok(unsafe { Rc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) @@ -3162,6 +3228,7 @@ impl> ToRcSlice for I { (low, high) ); + // SAFETY: Untriaged. unsafe { // SAFETY: We need to ensure that the iterator has an exact length and we have. Rc::from_iter_exact(self, low) @@ -3330,6 +3397,7 @@ impl Weak { #[inline] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_raw_in(ptr, Global) } } @@ -3453,6 +3521,7 @@ impl Weak { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&this.alloc) }; (result, alloc) } @@ -3561,6 +3630,7 @@ impl Weak { if inner.strong() == 0 { None } else { + // SAFETY: Untriaged. unsafe { inner.inc_strong(); Some(Rc::from_inner_in(self.ptr, self.alloc.clone())) @@ -3604,6 +3674,7 @@ impl Weak { // We are careful to *not* create a reference covering the "data" field, as // the field may be mutated concurrently (for example, if the last `Rc` // is dropped, the data field will be dropped in-place). + // SAFETY: Untriaged. Some(unsafe { let ptr = self.ptr.as_ptr(); WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } @@ -3691,6 +3762,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { // the weak count starts at 1, and will only go to zero if all // the strong pointers have disappeared. if inner.weak() == 0 { + // SAFETY: Untriaged. unsafe { self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())); } @@ -4242,6 +4314,7 @@ impl UniqueRc { && align_of::() == align_of::() && UniqueRc::weak_count(&this) == 0 { + // SAFETY: Untriaged. unsafe { let ptr = UniqueRc::into_raw(this); let value = ptr.read(); @@ -4290,6 +4363,7 @@ impl UniqueRc { && align_of::() == align_of::() && UniqueRc::weak_count(&this) == 0 { + // SAFETY: Untriaged. unsafe { let ptr = UniqueRc::into_raw(this); let value = ptr.read(); @@ -4306,6 +4380,7 @@ impl UniqueRc { #[cfg(not(no_global_oom_handling))] fn unwrap(this: Self) -> T { let this = ManuallyDrop::new(this); + // SAFETY: Untriaged. let val: T = unsafe { ptr::read(&**this) }; let _weak = Weak { ptr: this.ptr, alloc: Global }; @@ -4317,12 +4392,15 @@ impl UniqueRc { impl UniqueRc { #[cfg(not(no_global_oom_handling))] unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcInner. + // SAFETY: Untriaged. let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner }; Self { + // SAFETY: Untriaged. ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, _marker: PhantomData, _marker2: PhantomData, @@ -4411,6 +4489,7 @@ impl UniqueRc { #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); + // SAFETY: Untriaged. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -4441,6 +4520,7 @@ impl UniqueRc { impl UniqueRc, A> { unsafe fn assume_init(self) -> UniqueRc { let (ptr, alloc) = UniqueRc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { UniqueRc::from_inner_in(ptr.cast(), alloc) } } } @@ -4468,6 +4548,7 @@ impl DerefMut for UniqueRc { #[unstable(feature = "unique_rc_arc", issue = "112566")] unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { // destroy the contained object drop_in_place(DerefMut::deref_mut(self)); @@ -4499,6 +4580,7 @@ impl UniqueRcUninit { #[cfg(not(no_global_oom_handling))] fn new(for_value: &T, alloc: A) -> UniqueRcUninit { let layout = Layout::for_value(for_value); + // SAFETY: Untriaged. let ptr = unsafe { Rc::allocate_for_layout( layout, @@ -4513,6 +4595,7 @@ impl UniqueRcUninit { /// returning an error if allocation fails. fn try_new(for_value: &T, alloc: A) -> Result, AllocError> { let layout = Layout::for_value(for_value); + // SAFETY: Untriaged. let ptr = unsafe { Rc::try_allocate_for_layout( layout, @@ -4526,6 +4609,7 @@ impl UniqueRcUninit { /// Returns the pointer to be written into to initialize the [`Rc`]. fn data_ptr(&mut self) -> *mut T { let offset = data_offset_alignment(self.layout_for_value.alignment()); + // SAFETY: Untriaged. unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index e6b540f093ba5..d729eb7e92199 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -450,6 +450,7 @@ impl [T] { // allocated above with the capacity of `s`, and initialize to `s.len()` in // ptr::copy_to_non_overlapping below. if len > 0 { + // SAFETY: Untriaged. unsafe { s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), len); v.set_len(len); @@ -479,6 +480,7 @@ impl [T] { #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn into_vec(self: Box) -> Vec { + // SAFETY: Untriaged. unsafe { let len = self.len(); let (b, alloc) = Box::into_raw_with_allocator(self); @@ -531,6 +533,7 @@ impl [T] { // If `m > 0`, there are remaining bits up to the leftmost '1'. while m > 0 { // `buf.extend(buf)`: + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping::( buf.as_ptr(), @@ -551,6 +554,7 @@ impl [T] { let rem_len = capacity - buf.len(); // `self.len() * rem` if rem_len > 0 { // `buf.extend(buf[0 .. rem_len])`: + // SAFETY: Untriaged. unsafe { // This is non-overlapping since `2^expn > rem`. ptr::copy_nonoverlapping::( diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index c6d9007bbbc45..b9e79160f8d8d 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -73,6 +73,7 @@ impl> Join<&str> for [S] { type Output = String; fn join(slice: &Self, sep: &str) -> String { + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) } } } @@ -180,6 +181,7 @@ where result.extend_from_slice(first); + // SAFETY: Untriaged. unsafe { let pos = result.len(); debug_assert!(reserved_len >= pos); @@ -248,6 +250,7 @@ impl ToOwned for str { #[inline] fn to_owned(&self) -> String { + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } } @@ -316,6 +319,7 @@ impl str { _ => None, } { if let [to_byte] = to.as_bytes() { + // SAFETY: Untriaged. return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) }; } } @@ -328,10 +332,12 @@ impl str { let mut result = String::with_capacity(default_capacity); let mut last_end = 0; for (start, part) in self.match_indices(from) { + // SAFETY: Untriaged. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } + // SAFETY: Untriaged. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -368,10 +374,12 @@ impl str { let mut result = String::with_capacity(32); let mut last_end = 0; for (start, part) in self.match_indices(pat).take(count) { + // SAFETY: Untriaged. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } + // SAFETY: Untriaged. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -785,6 +793,7 @@ impl str { #[inline] pub fn into_string(self: Box) -> String { let slice = Box::<[u8]>::from(self); + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(slice.into_vec()) } } @@ -814,6 +823,7 @@ impl str { #[stable(feature = "repeat_str", since = "1.16.0")] #[inline] pub fn repeat(&self, n: usize) -> String { + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } } @@ -903,6 +913,7 @@ impl str { #[must_use] #[inline] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { + // SAFETY: Untriaged. unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } } @@ -960,7 +971,9 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & } ascii_prefix_len += N; + // SAFETY: Untriaged. slice = unsafe { slice.get_unchecked(N..) }; + // SAFETY: Untriaged. out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; } @@ -975,10 +988,13 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); } ascii_prefix_len += 1; + // SAFETY: Untriaged. slice = unsafe { slice.get_unchecked(1..) }; + // SAFETY: Untriaged. out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; } + // SAFETY: Untriaged. unsafe { // SAFETY: ascii_prefix_len bytes have been initialized above out.set_len(ascii_prefix_len); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index cc321660e6ea4..19f06cbedac34 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -790,6 +790,7 @@ impl String { let (chunks, []) = v.as_chunks::<2>() else { return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes }); }; + // SAFETY: Untriaged. match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => char::decode_utf16(chunks.iter().copied().map(u16::from_le_bytes)) @@ -825,6 +826,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_from_utf16_endian", since = "1.98.0")] pub fn from_utf16le_lossy(v: &[u8]) -> String { + // SAFETY: Untriaged. match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", @@ -863,6 +865,7 @@ impl String { let (chunks, []) = v.as_chunks::<2>() else { return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes }); }; + // SAFETY: Untriaged. match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => char::decode_utf16(chunks.iter().copied().map(u16::from_be_bytes)) @@ -898,6 +901,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_from_utf16_endian", since = "1.98.0")] pub fn from_utf16be_lossy(v: &[u8]) -> String { + // SAFETY: Untriaged. match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", @@ -981,6 +985,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { + // SAFETY: Untriaged. unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } } @@ -1125,6 +1130,7 @@ impl String { let additional: Saturating = slice.iter().map(|x| Saturating(x.len())).sum(); self.reserve(additional.0); let (ptr, len, cap) = core::mem::take(self).into_raw_parts(); + // SAFETY: Untriaged. unsafe { let mut dst = ptr.add(len); for new in slice { @@ -1513,6 +1519,7 @@ impl String { pub fn pop(&mut self) -> Option { let ch = self.chars().rev().next()?; let newlen = self.len() - ch.len_utf8(); + // SAFETY: Untriaged. unsafe { self.vec.set_len(newlen); } @@ -1551,6 +1558,7 @@ impl String { let next = idx + ch.len_utf8(); let len = self.len(); + // SAFETY: Untriaged. unsafe { ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); self.vec.set_len(len - (next - idx)); @@ -1624,6 +1632,7 @@ impl String { len += count; } + // SAFETY: Untriaged. unsafe { self.vec.set_len(len); } @@ -1671,6 +1680,7 @@ impl String { fn drop(&mut self) { let new_len = self.idx - self.del_bytes; debug_assert!(new_len <= self.s.len()); + // SAFETY: Untriaged. unsafe { self.s.vec.set_len(new_len) }; } } @@ -1928,6 +1938,7 @@ impl String { pub fn split_off(&mut self, at: usize) -> String { assert!(self.is_char_boundary(at)); let other = self.vec.split_off(at); + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(other) } } @@ -2104,6 +2115,7 @@ impl String { "end of range should be a character boundary" ); + // SAFETY: Untriaged. unsafe { self.as_mut_vec() }.splice(checked_range, replace_with.bytes()); } @@ -2189,6 +2201,7 @@ impl String { #[inline] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); + // SAFETY: Untriaged. unsafe { from_boxed_utf8_unchecked(slice) } } @@ -2220,6 +2233,7 @@ impl String { #[inline] pub fn leak<'a>(self) -> &'a mut str { let slice = self.vec.leak(); + // SAFETY: Untriaged. unsafe { from_utf8_unchecked_mut(slice) } } } @@ -3455,6 +3469,7 @@ impl IntoChars { #[inline] pub fn into_string(self) -> String { // Safety: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(self.bytes.collect()) } } @@ -3551,6 +3566,7 @@ unsafe impl Send for Drain<'_> {} #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_> { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { // Use Vec::drain. "Reaffirm" the bounds checks to avoid // panic code being inserted again. diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 5e1344c0994cb..9e780b795317c 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -300,10 +300,12 @@ unsafe impl CloneFromCell for Arc {} impl Arc { unsafe fn from_inner(ptr: NonNull>) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner_in(ptr, Global) } } unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_ptr_in(ptr, Global) } } } @@ -312,6 +314,7 @@ impl Arc { #[inline] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); + // SAFETY: Untriaged. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -322,6 +325,7 @@ impl Arc { #[inline] unsafe fn from_ptr_in(ptr: *mut ArcInner, alloc: A) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } } } @@ -442,6 +446,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, }); + // SAFETY: Untriaged. unsafe { Self::from_inner(Box::leak(x).into()) } } @@ -527,6 +532,7 @@ impl Arc { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit() -> Arc> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr(Arc::allocate_for_layout( Layout::new::(), @@ -559,6 +565,7 @@ impl Arc { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed() -> Arc> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr(Arc::allocate_for_layout( Layout::new::(), @@ -574,6 +581,7 @@ impl Arc { #[stable(feature = "pin", since = "1.33.0")] #[must_use] pub fn pin(data: T) -> Pin> { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Arc::new(data)) } } @@ -581,6 +589,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_pin(data: T) -> Result>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } } @@ -605,6 +614,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, })?; + // SAFETY: Untriaged. unsafe { Ok(Self::from_inner(Box::leak(x).into())) } } @@ -630,6 +640,7 @@ impl Arc { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn try_new_uninit() -> Result>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Arc::from_ptr(Arc::try_allocate_for_layout( Layout::new::(), @@ -662,6 +673,7 @@ impl Arc { /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] pub fn try_new_zeroed() -> Result>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Arc::from_ptr(Arc::try_allocate_for_layout( Layout::new::(), @@ -698,6 +710,7 @@ impl Arc { && align_of::() == align_of::() && Arc::is_unique(&this) { + // SAFETY: Untriaged. unsafe { let ptr = Arc::into_raw(this); let value = ptr.read(); @@ -745,6 +758,7 @@ impl Arc { && align_of::() == align_of::() && Arc::is_unique(&this) { + // SAFETY: Untriaged. unsafe { let ptr = Arc::into_raw(this); let value = ptr.read(); @@ -787,6 +801,7 @@ impl Arc { alloc, ); let (ptr, alloc) = Box::into_unique(x); + // SAFETY: Untriaged. unsafe { Self::from_inner_in(ptr.into(), alloc) } } @@ -816,6 +831,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_in(alloc: A) -> Arc, A> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in( Arc::allocate_for_layout( @@ -853,6 +869,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_in(alloc: A) -> Arc, A> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in( Arc::allocate_for_layout( @@ -911,6 +928,7 @@ impl Arc { }, alloc, )); + // SAFETY: Untriaged. let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); let init_ptr: NonNull> = uninit_ptr.cast(); @@ -926,6 +944,7 @@ impl Arc { // Now we can properly initialize the inner value and turn our weak // reference into a strong reference. + // SAFETY: Untriaged. unsafe { let inner = init_ptr.as_ptr(); ptr::write(&raw mut (*inner).data, data); @@ -964,6 +983,7 @@ impl Arc { where A: 'static, { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } } @@ -975,6 +995,7 @@ impl Arc { where A: 'static, { + // SAFETY: Untriaged. unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } } @@ -1005,6 +1026,7 @@ impl Arc { alloc, )?; let (ptr, alloc) = Box::into_unique(x); + // SAFETY: Untriaged. Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) } @@ -1035,6 +1057,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Arc::from_ptr_in( Arc::try_allocate_for_layout( @@ -1073,6 +1096,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { + // SAFETY: Untriaged. unsafe { Ok(Arc::from_ptr_in( Arc::try_allocate_for_layout( @@ -1127,7 +1151,9 @@ impl Arc { acquire!(this.inner().strong); let this = ManuallyDrop::new(this); + // SAFETY: Untriaged. let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; + // SAFETY: Untriaged. let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator // Make a weak pointer to clean up the implicit strong-weak reference @@ -1254,6 +1280,7 @@ impl Arc { // safety conditions as `ptr::drop_in_place`. let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) }; + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&this.alloc) }; drop(Weak { ptr: this.ptr, alloc }); @@ -1287,6 +1314,7 @@ impl Arc<[T]> { #[stable(feature = "new_uninit", since = "1.82.0")] #[must_use] pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr(Arc::allocate_for_slice(len)) } } @@ -1313,6 +1341,7 @@ impl Arc<[T]> { #[stable(feature = "new_zeroed_alloc", since = "1.92.0")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr(Arc::allocate_for_layout( Layout::array::(len).unwrap(), @@ -1353,6 +1382,7 @@ impl Arc<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } } @@ -1381,6 +1411,7 @@ impl Arc<[T], A> { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in( Arc::allocate_for_layout( @@ -1460,6 +1491,7 @@ impl Arc, A> { #[inline] pub unsafe fn assume_init(self) -> Arc { let (ptr, alloc) = Arc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { Arc::from_inner_in(ptr.cast(), alloc) } } } @@ -1521,6 +1553,7 @@ impl Arc { let mut in_progress: UniqueArcUninit = UniqueArcUninit::new(value, alloc); // Initialize with clone of value. + // SAFETY: Untriaged. unsafe { // Clone. If the clone panics, `in_progress` will be dropped and clean up. value.clone_to_uninit(in_progress.data_ptr().cast()); @@ -1549,6 +1582,7 @@ impl Arc { let mut in_progress: UniqueArcUninit = UniqueArcUninit::try_new(value, alloc)?; // Initialize with clone of value. + // SAFETY: Untriaged. let initialized_clone = unsafe { // Clone. If the clone panics, `in_progress` will be dropped and clean up. value.clone_to_uninit(in_progress.data_ptr().cast()); @@ -1595,6 +1629,7 @@ impl Arc<[mem::MaybeUninit], A> { #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { let (ptr, alloc) = Arc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -1667,6 +1702,7 @@ impl Arc { #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. unsafe { Arc::from_raw_in(ptr, Global) } } @@ -1729,6 +1765,7 @@ impl Arc { #[inline] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] pub unsafe fn increment_strong_count(ptr: *const T) { + // SAFETY: Untriaged. unsafe { Arc::increment_strong_count_in(ptr, Global) } } @@ -1769,6 +1806,7 @@ impl Arc { #[inline] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] pub unsafe fn decrement_strong_count(ptr: *const T) { + // SAFETY: Untriaged. unsafe { Arc::decrement_strong_count_in(ptr, Global) } } } @@ -1809,6 +1847,7 @@ impl Arc { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&this.alloc) }; (ptr, alloc) } @@ -1914,6 +1953,7 @@ impl Arc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { + // SAFETY: Untriaged. unsafe { let offset = data_offset(ptr); @@ -2075,6 +2115,7 @@ impl Arc { A: Clone, { // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop + // SAFETY: Untriaged. let arc = unsafe { mem::ManuallyDrop::new(Arc::from_raw_in(ptr, alloc)) }; // Now increase refcount, but don't drop new refcount either let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); @@ -2120,6 +2161,7 @@ impl Arc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { + // SAFETY: Untriaged. unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; } @@ -2130,6 +2172,7 @@ impl Arc { // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. + // SAFETY: Untriaged. unsafe { self.ptr.as_ref() } } @@ -2146,6 +2189,7 @@ impl Arc { // Destroy the data at this time, even though we must not free the box // allocation itself (there might still be weak pointers lying around). // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; } @@ -2190,6 +2234,7 @@ impl Arc { let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + // SAFETY: Untriaged. unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) } } @@ -2208,6 +2253,7 @@ impl Arc { let ptr = allocate(layout)?; + // SAFETY: Untriaged. let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }; Ok(inner) @@ -2219,8 +2265,10 @@ impl Arc { mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> *mut ArcInner { let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); + // SAFETY: Untriaged. debug_assert_eq!(unsafe { Layout::for_value_raw(inner) }, layout); + // SAFETY: Untriaged. unsafe { (&raw mut (*inner).strong).write(atomic::AtomicUsize::new(1)); (&raw mut (*inner).weak).write(atomic::AtomicUsize::new(1)); @@ -2236,6 +2284,7 @@ impl Arc { #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. + // SAFETY: Untriaged. unsafe { Arc::allocate_for_layout( Layout::for_value_raw(ptr), @@ -2247,6 +2296,7 @@ impl Arc { #[cfg(not(no_global_oom_handling))] fn from_box_in(src: Box) -> Arc { + // SAFETY: Untriaged. unsafe { let value_size = size_of_val(&*src); let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); @@ -2272,6 +2322,7 @@ impl Arc<[T]> { /// Allocates an `ArcInner<[T]>` with the given length. #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice(len: usize) -> *mut ArcInner<[T]> { + // SAFETY: Untriaged. unsafe { Self::allocate_for_layout( Layout::array::(len).unwrap(), @@ -2287,6 +2338,7 @@ impl Arc<[T]> { /// bind `T: TrivialClone`. #[cfg(not(no_global_oom_handling))] unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { + // SAFETY: Untriaged. unsafe { let ptr = Self::allocate_for_slice(v.len()); @@ -2313,6 +2365,7 @@ impl Arc<[T]> { impl Drop for Guard { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { let slice = from_raw_parts_mut(self.elems, self.n_elems); ptr::drop_in_place(slice); @@ -2322,6 +2375,7 @@ impl Arc<[T]> { } } + // SAFETY: Untriaged. unsafe { let ptr = Self::allocate_for_slice(len); @@ -2351,6 +2405,7 @@ impl Arc<[T], A> { #[inline] #[cfg(not(no_global_oom_handling))] unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut ArcInner<[T]> { + // SAFETY: Untriaged. unsafe { Arc::allocate_for_layout( Layout::array::(len).unwrap(), @@ -2371,6 +2426,7 @@ trait ArcFromSlice { impl ArcFromSlice for Arc<[T]> { #[inline] default fn from_slice(v: &[T]) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } } } @@ -2435,6 +2491,7 @@ impl Clone for Arc { abort(); } + // SAFETY: Untriaged. unsafe { Self::from_inner_in(self.ptr, self.alloc.clone()) } } } @@ -2574,6 +2631,7 @@ impl Arc { let mut in_progress: UniqueArcUninit = UniqueArcUninit::new(&**this, this.alloc.clone()); + // SAFETY: Untriaged. unsafe { // Initialize `in_progress` with move of **this. // We have to express this in terms of bytes because `T: ?Sized`; there is no @@ -2603,6 +2661,7 @@ impl Arc { // As with `get_mut()`, the unsafety is ok because our reference was // either unique to begin with, or became one upon cloning the contents. + // SAFETY: Untriaged. unsafe { Self::get_mut_unchecked(this) } } } @@ -2677,6 +2736,7 @@ impl Arc { // reference count is guaranteed to be 1 at this point, and we required // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. + // SAFETY: Untriaged. unsafe { Some(Arc::get_mut_unchecked(this)) } } else { None @@ -2748,6 +2808,7 @@ impl Arc { pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { // We are careful to *not* create a reference covering the "count" fields, as // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + // SAFETY: Untriaged. unsafe { &mut (*this.ptr.as_ptr()).data } } @@ -2907,6 +2968,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Arc { Likely decrement_strong_count or from_raw were called too many times.", ); + // SAFETY: Untriaged. unsafe { self.drop_slow(); } @@ -2939,6 +3001,7 @@ impl Arc { T: Any + Send + Sync, { if (*self).is::() { + // SAFETY: Untriaged. unsafe { let (ptr, alloc) = Arc::into_inner_with_allocator(self); Ok(Arc::from_inner_in(ptr.cast(), alloc)) @@ -2980,6 +3043,7 @@ impl Arc { where T: Any + Send + Sync, { + // SAFETY: Untriaged. unsafe { let (ptr, alloc) = Arc::into_inner_with_allocator(self); Arc::from_inner_in(ptr.cast(), alloc) @@ -3087,6 +3151,7 @@ impl Weak { #[inline] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. unsafe { Weak::from_raw_in(ptr, Global) } } @@ -3209,6 +3274,7 @@ impl Weak { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(&this.alloc) }; (result, alloc) } @@ -3395,6 +3461,7 @@ impl Weak { // We are careful to *not* create a reference covering the "data" field, as // the field may be mutated concurrently (for example, if the last `Arc` // is dropped, the data field will be dropped in-place). + // SAFETY: Untriaged. Some(unsafe { WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } }) } } @@ -3552,6 +3619,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Weak { Likely decrement_strong_count or from_raw were called too many times.", ); + // SAFETY: Untriaged. unsafe { self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr())) } @@ -3789,6 +3857,7 @@ impl Default for Arc { /// assert_eq!(*x, 0); /// ``` fn default() -> Arc { + // SAFETY: Untriaged. unsafe { Self::from_inner( Box::leak(Box::write( @@ -3838,6 +3907,7 @@ impl Default for Arc { let arc: Arc<[u8]> = Default::default(); debug_assert!(core::str::from_utf8(&*arc).is_ok()); let (ptr, alloc) = Arc::into_inner_with_allocator(arc); + // SAFETY: Untriaged. unsafe { Arc::from_ptr_in(ptr.as_ptr() as *mut ArcInner, alloc) } } } @@ -3856,6 +3926,7 @@ impl Default for Arc { NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. let this: mem::ManuallyDrop> = +// SAFETY: Untriaged. unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; (*this).clone() } @@ -3878,6 +3949,7 @@ impl Default for Arc<[T]> { let inner: NonNull> = inner.cast(); // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. let this: mem::ManuallyDrop> = +// SAFETY: Untriaged. unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; return (*this).clone(); } @@ -3897,6 +3969,7 @@ where { #[inline] fn default() -> Self { + // SAFETY: Untriaged. unsafe { Pin::new_unchecked(Arc::::default()) } } } @@ -4005,6 +4078,7 @@ impl From<&str> for Arc { #[inline] fn from(v: &str) -> Arc { let arc = Arc::<[u8]>::from(v.as_bytes()); + // SAFETY: Untriaged. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const str) } } } @@ -4082,6 +4156,7 @@ impl From> for Arc<[T], A> { /// ``` #[inline] fn from(v: Vec) -> Arc<[T], A> { + // SAFETY: Untriaged. unsafe { let (vec_ptr, len, cap, alloc) = v.into_raw_parts_with_alloc(); @@ -4150,6 +4225,7 @@ impl TryFrom> for Arc<[T; N], A> { fn try_from(boxed_slice: Arc<[T], A>) -> Result { if boxed_slice.len() == N { let (ptr, alloc) = Arc::into_inner_with_allocator(boxed_slice); + // SAFETY: Untriaged. Ok(unsafe { Arc::from_inner_in(ptr.cast(), alloc) }) } else { Err(boxed_slice) @@ -4229,6 +4305,7 @@ impl> ToArcSlice for I { (low, high) ); + // SAFETY: Untriaged. unsafe { // SAFETY: We need to ensure that the iterator has an exact length and we have. Arc::from_iter_exact(self, low) @@ -4297,6 +4374,7 @@ impl UniqueArcUninit { #[cfg(not(no_global_oom_handling))] fn new(for_value: &T, alloc: A) -> UniqueArcUninit { let layout = Layout::for_value(for_value); + // SAFETY: Untriaged. let ptr = unsafe { Arc::allocate_for_layout( layout, @@ -4311,6 +4389,7 @@ impl UniqueArcUninit { /// returning an error if allocation fails. fn try_new(for_value: &T, alloc: A) -> Result, AllocError> { let layout = Layout::for_value(for_value); + // SAFETY: Untriaged. let ptr = unsafe { Arc::try_allocate_for_layout( layout, @@ -4324,6 +4403,7 @@ impl UniqueArcUninit { /// Returns the pointer to be written into to initialize the [`Arc`]. fn data_ptr(&mut self) -> *mut T { let offset = data_offset_alignment(self.layout_for_value.alignment()); + // SAFETY: Untriaged. unsafe { self.ptr.as_ptr().byte_add(offset) as *mut T } } @@ -4696,6 +4776,7 @@ impl UniqueArc { && align_of::() == align_of::() && UniqueArc::weak_count(&this) == 0 { + // SAFETY: Untriaged. unsafe { let ptr = UniqueArc::into_raw(this); let value = ptr.read(); @@ -4744,6 +4825,7 @@ impl UniqueArc { && align_of::() == align_of::() && UniqueArc::weak_count(&this) == 0 { + // SAFETY: Untriaged. unsafe { let ptr = UniqueArc::into_raw(this); let value = ptr.read(); @@ -4760,6 +4842,7 @@ impl UniqueArc { #[cfg(not(no_global_oom_handling))] fn unwrap(this: Self) -> T { let this = ManuallyDrop::new(this); + // SAFETY: Untriaged. let val: T = unsafe { ptr::read(&**this) }; let _weak = Weak { ptr: this.ptr, alloc: Global }; @@ -4771,12 +4854,15 @@ impl UniqueArc { impl UniqueArc { #[cfg(not(no_global_oom_handling))] unsafe fn from_raw(ptr: *const T) -> Self { + // SAFETY: Untriaged. let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original ArcInner. + // SAFETY: Untriaged. let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; Self { + // SAFETY: Untriaged. ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, _marker: PhantomData, _marker2: PhantomData, @@ -4868,6 +4954,7 @@ impl UniqueArc { #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); + // SAFETY: Untriaged. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -4910,6 +4997,7 @@ impl UniqueArc { impl UniqueArc, A> { unsafe fn assume_init(self) -> UniqueArc { let (ptr, alloc) = UniqueArc::into_inner_with_allocator(self); + // SAFETY: Untriaged. unsafe { UniqueArc::from_inner_in(ptr.cast(), alloc) } } } @@ -4952,6 +5040,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { // SAFETY: This pointer was allocated at creation time so we know it is valid. let _weak = Weak { ptr: self.ptr, alloc: &self.alloc }; + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).data) }; } } diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs index 0e36c91f466fd..43e3ce8d6701e 100644 --- a/library/alloc/src/task.rs +++ b/library/alloc/src/task.rs @@ -189,6 +189,7 @@ fn raw_waker(waker: Arc) -> RawWaker { // within the vtables. #[inline(always)] unsafe fn clone_waker(waker: *const ()) -> RawWaker { + // SAFETY: Untriaged. unsafe { Arc::increment_strong_count(waker as *const W) }; RawWaker::new( waker, @@ -198,18 +199,21 @@ fn raw_waker(waker: Arc) -> RawWaker { // Wake by value, moving the Arc into the Wake::wake function unsafe fn wake(waker: *const ()) { + // SAFETY: Untriaged. let waker = unsafe { Arc::from_raw(waker as *const W) }; ::wake(waker); } // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it unsafe fn wake_by_ref(waker: *const ()) { + // SAFETY: Untriaged. let waker = unsafe { ManuallyDrop::new(Arc::from_raw(waker as *const W)) }; ::wake_by_ref(&waker); } // Decrement the reference count of the Arc on drop unsafe fn drop_waker(waker: *const ()) { + // SAFETY: Untriaged. unsafe { Arc::decrement_strong_count(waker as *const W) }; } @@ -401,6 +405,7 @@ fn local_raw_waker(waker: Rc) -> RawWaker { // always inline. #[inline(always)] unsafe fn clone_waker(waker: *const ()) -> RawWaker { + // SAFETY: Untriaged. unsafe { Rc::increment_strong_count(waker as *const W) }; RawWaker::new( waker, @@ -410,18 +415,21 @@ fn local_raw_waker(waker: Rc) -> RawWaker { // Wake by value, moving the Rc into the LocalWake::wake function unsafe fn wake(waker: *const ()) { + // SAFETY: Untriaged. let waker = unsafe { Rc::from_raw(waker as *const W) }; ::wake(waker); } // Wake by reference, wrap the waker in ManuallyDrop to avoid dropping it unsafe fn wake_by_ref(waker: *const ()) { + // SAFETY: Untriaged. let waker = unsafe { ManuallyDrop::new(Rc::from_raw(waker as *const W)) }; ::wake_by_ref(&waker); } // Decrement the reference count of the Rc on drop unsafe fn drop_waker(waker: *const ()) { + // SAFETY: Untriaged. unsafe { Rc::decrement_strong_count(waker as *const W) }; } diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index d12dea20b33cb..bef7c86cc102d 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -62,6 +62,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { #[must_use] #[inline] pub fn allocator(&self) -> &A { + // SAFETY: Untriaged. unsafe { self.vec.as_ref().allocator() } } @@ -101,6 +102,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { // 4. Do *not* drop self, as everything is put in a consistent state already, there is nothing to do let mut this = ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { let source_vec = this.vec.as_mut(); @@ -153,6 +155,7 @@ impl Iterator for Drain<'_, T, A> { #[inline] fn next(&mut self) -> Option { + // SAFETY: Untriaged. self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) }) } @@ -165,6 +168,7 @@ impl Iterator for Drain<'_, T, A> { impl DoubleEndedIterator for Drain<'_, T, A> { #[inline] fn next_back(&mut self) -> Option { + // SAFETY: Untriaged. self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) }) } } @@ -178,6 +182,7 @@ impl Drop for Drain<'_, T, A> { impl<'r, 'a, T, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { fn drop(&mut self) { if self.0.tail_len > 0 { + // SAFETY: Untriaged. unsafe { let source_vec = self.0.vec.as_mut(); // memmove back untouched tail, update to new length @@ -202,6 +207,7 @@ impl Drop for Drain<'_, T, A> { if T::IS_ZST { // ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount. // this can be achieved by manipulating the Vec length instead of moving values out from `iter`. + // SAFETY: Untriaged. unsafe { let vec = vec.as_mut(); let old_len = vec.len(); @@ -225,6 +231,7 @@ impl Drop for Drain<'_, T, A> { // lead to invalid pointer arithmetic below. let drop_ptr = iter.as_slice().as_ptr(); + // SAFETY: Untriaged. unsafe { // drop_ptr comes from a slice::Iter which only gives us a &[T] but for drop_in_place // a pointer with mutable provenance is necessary. Therefore we must reconstruct diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index a4c4c19682195..a457bf7c4ffcc 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -43,6 +43,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { let Range { start, end } = slice::range(range, ..old_len); // Guard against the vec getting leaked (leak amplification) + // SAFETY: Untriaged. unsafe { vec.set_len(0); } @@ -139,10 +140,12 @@ where // SAFETY: we have not yet touched elements starting at `self.idx`. let valid_tail = +// SAFETY: Untriaged. unsafe { slice::from_raw_parts(start.add(self.idx), self.old_len - self.idx) }; // SAFETY: `end - idx <= old_len - idx`, because `end <= old_len`. Also `idx <= end` by invariant. let (remainder, skipped_tail) = +// SAFETY: Untriaged. unsafe { valid_tail.split_at_unchecked(self.end - self.idx) }; f.debug_struct("ExtractIf") diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index a5566f70fea3c..6417a176fd613 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -251,6 +251,7 @@ where I: Iterator + InPlaceCollect, ::Source: AsVecIntoIter, { + // SAFETY: Untriaged. let (src_buf, src_ptr, src_cap, mut dst_buf, dst_end, dst_cap) = unsafe { let inner = iterator.as_inner().as_into_iter(); ( @@ -269,6 +270,7 @@ where SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf.as_ptr() as *mut T, dst_end) }; + // SAFETY: Untriaged. let src = unsafe { iterator.as_inner().as_into_iter() }; // check if SourceIter contract was upheld // caveat: if they weren't we might not even make it to this point @@ -278,6 +280,7 @@ where // then the source pointer will stay in its initial position and we can't use it as reference if src.ptr != src_ptr { debug_assert!( + // SAFETY: Untriaged. unsafe { dst_buf.add(len).cast() } <= src.ptr, "InPlaceIterable contract violation, write pointer advanced beyond read pointer" ); @@ -306,6 +309,7 @@ where let alloc = Global; debug_assert_ne!(src_cap, 0); debug_assert_ne!(dst_cap, 0); + // SAFETY: Untriaged. unsafe { // The old allocation exists, therefore it must have a valid layout. let src_align = align_of::(); @@ -328,6 +332,7 @@ where mem::forget(dst_guard); + // SAFETY: Untriaged. unsafe { Vec::from_parts(dst_buf, len, dst_cap) } } @@ -335,6 +340,7 @@ fn write_in_place_with_drop( src_end: *const T, ) -> impl FnMut(InPlaceDrop, T) -> Result, !> { move |mut sink, item| { + // SAFETY: Untriaged. unsafe { // the InPlaceIterable contract cannot be verified precisely here since // try_fold has an exclusive reference to the source pointer @@ -375,6 +381,7 @@ where let sink = self.try_fold::<_, _, Result<_, !>>(sink, write_in_place_with_drop(end)).into_ok(); // iteration succeeded, don't drop head + // SAFETY: Untriaged. unsafe { ManuallyDrop::new(sink).dst.offset_from_unsigned(dst_buf) } } } @@ -391,6 +398,7 @@ where // Safety: InplaceIterable contract guarantees that for every element we read // one slot in the underlying storage will have been freed up and we can immediately // write back the result. + // SAFETY: Untriaged. unsafe { let dst = dst_buf.add(i); debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs index 5c3d598cdef0c..50d3b4d7ab004 100644 --- a/library/alloc/src/vec/in_place_drop.rs +++ b/library/alloc/src/vec/in_place_drop.rs @@ -13,6 +13,7 @@ pub(super) struct InPlaceDrop { impl InPlaceDrop { fn len(&self) -> usize { + // SAFETY: Untriaged. unsafe { self.dst.offset_from_unsigned(self.inner) } } } @@ -20,6 +21,7 @@ impl InPlaceDrop { impl Drop for InPlaceDrop { #[inline] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { self.inner.cast_slice(self.len()).drop_in_place() } } } @@ -37,6 +39,7 @@ pub(super) struct InPlaceDstDataSrcBufDrop { impl Drop for InPlaceDstDataSrcBufDrop { #[inline] fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { let _drop_allocation = RawVec::::from_nonnull_in(self.ptr.cast::(), self.src_cap, Global); diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 4b25634326e16..bf4e32285d164 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -21,10 +21,12 @@ use crate::raw_vec::RawVec; macro non_null { (mut $place:expr, $t:ident) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block +// SAFETY: Untriaged. unsafe { &mut *((&raw mut $place) as *mut NonNull<$t>) } }}, ($place:expr, $t:ident) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block +// SAFETY: Untriaged. unsafe { *((&raw const $place) as *const NonNull<$t>) } }}, } @@ -86,6 +88,7 @@ impl IntoIter { /// ``` #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] pub fn as_slice(&self) -> &[T] { + // SAFETY: Untriaged. unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len()) } } @@ -104,6 +107,7 @@ impl IntoIter { /// ``` #[stable(feature = "vec_into_iter_as_slice", since = "1.15.0")] pub fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: Untriaged. unsafe { &mut *self.as_raw_mut_slice() } } @@ -153,6 +157,7 @@ impl IntoIter { // Dropping the remaining elements can panic, so this needs to be // done only after updating the other fields. + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(remaining); } @@ -196,6 +201,7 @@ impl IntoIter { /// memory if there are any remaining elements. #[inline] unsafe fn dealloc_only(&mut self) { + // SAFETY: Untriaged. unsafe { // SAFETY: our caller promises not to touch `*self` again let alloc = ManuallyDrop::take(&mut self.alloc); @@ -263,9 +269,11 @@ impl Iterator for IntoIter { return None; } let old = self.ptr; + // SAFETY: Untriaged. self.ptr = unsafe { old.add(1) }; old }; + // SAFETY: Untriaged. Some(unsafe { ptr.read() }) } @@ -274,6 +282,7 @@ impl Iterator for IntoIter { let exact = if T::IS_ZST { self.end.addr().wrapping_sub(self.ptr.as_ptr().addr()) } else { + // SAFETY: Untriaged. unsafe { non_null!(self.end, T).offset_from_unsigned(self.ptr) } }; (exact, Some(exact)) @@ -317,17 +326,20 @@ impl Iterator for IntoIter { if len < N { self.forget_remaining_elements(); // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct + // SAFETY: Untriaged. return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, 0..len) }); } self.end = self.end.wrapping_byte_sub(N); // Safety: ditto + // SAFETY: Untriaged. return Ok(unsafe { raw_ary.transpose().assume_init() }); } if len < N { // Safety: `len` indicates that this many elements are available and we just checked that // it fits into the array. + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); self.forget_remaining_elements(); @@ -337,6 +349,7 @@ impl Iterator for IntoIter { // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N); self.ptr = self.ptr.add(N); @@ -433,11 +446,13 @@ impl DoubleEndedIterator for IntoIter { // Note that even though this is next_back() we're reading from `self.ptr`, not // `self.end`. We track our length using the byte offset from `self.ptr` to `self.end`, // so the end pointer may not be suitably aligned for T. + // SAFETY: Untriaged. Some(unsafe { ptr::read(self.ptr.as_ptr()) }) } else { if self.ptr == non_null!(self.end, T) { return None; } + // SAFETY: Untriaged. unsafe { self.end = self.end.sub(1); Some(ptr::read(self.end)) @@ -455,17 +470,20 @@ impl DoubleEndedIterator for IntoIter { if len < N { self.forget_remaining_elements(); // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct + // SAFETY: Untriaged. return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, N - len..N) }); } self.end = self.end.wrapping_byte_sub(N); // Safety: ditto + // SAFETY: Untriaged. return Ok(unsafe { MaybeUninit::array_assume_init(raw_ary) }); } if len < N { // Safety: `len` indicates that this many elements are available and we just checked that // it fits into the array. + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); self.forget_remaining_elements(); @@ -475,6 +493,7 @@ impl DoubleEndedIterator for IntoIter { // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping( self.ptr.add(len - N).as_ptr(), @@ -585,6 +604,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { impl Drop for DropGuard<'_, T, A> { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { self.0.dealloc_only(); } @@ -593,6 +613,7 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for IntoIter { let guard = DropGuard(self); // destroy the remaining elements + // SAFETY: Untriaged. unsafe { ptr::drop_in_place(guard.0.as_raw_mut_slice()); } diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index 04b50e5762986..a9167b726e88c 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -153,6 +153,7 @@ macro_rules! impl_is_zero_option_of_int { #[inline] fn is_zero(&self) -> bool { const { +// SAFETY: Untriaged. let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() }; assert!(none.is_none()); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index a619aa6e5427b..78c70b0942fb2 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -640,6 +640,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } } @@ -739,6 +740,7 @@ impl Vec { #[stable(feature = "box_vec_non_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_parts(ptr: NonNull, length: usize, capacity: usize) -> Self { + // SAFETY: Untriaged. unsafe { Self::from_parts_in(ptr, length, capacity, Global) } } @@ -895,10 +897,13 @@ impl Vec { // which is why we instead return a new slice in this case. if self.capacity() == 0 || T::IS_ZST { let me = ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { slice::from_raw_parts(NonNull::::dangling().as_ptr(), me.len) } } else { + // SAFETY: Untriaged. unsafe { core::intrinsics::const_make_global(self.as_mut_ptr().cast()) }; let me = ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { slice::from_raw_parts(me.as_ptr(), me.len) } } } @@ -1032,6 +1037,7 @@ const impl Vec { if len == self.buf.capacity() { self.buf.grow_one(); } +// SAFETY: Untriaged. unsafe { let end = self.as_mut_ptr().add(len); ptr::write(end, value); @@ -1193,6 +1199,7 @@ impl Vec { "Vec::from_raw_parts_in requires that length <= capacity", (length: usize = length, capacity: usize = capacity) => length <= capacity ); + // SAFETY: Untriaged. unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } } @@ -1308,6 +1315,7 @@ impl Vec { "Vec::from_parts_in requires that length <= capacity", (length: usize = length, capacity: usize = capacity) => length <= capacity ); + // SAFETY: Untriaged. unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } } @@ -1356,6 +1364,7 @@ impl Vec { let len = me.len(); let capacity = me.capacity(); let ptr = me.as_mut_ptr(); + // SAFETY: Untriaged. let alloc = unsafe { ptr::read(me.allocator()) }; (ptr, len, capacity, alloc) } @@ -1721,6 +1730,7 @@ impl Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T], A> { + // SAFETY: Untriaged. unsafe { self.shrink_to_fit(); let me = ManuallyDrop::new(self); @@ -2262,6 +2272,7 @@ impl Vec { if index >= len { assert_failed(index, len); } + // SAFETY: Untriaged. unsafe { // We replace self[index] with the last element. Note that if the // bounds check above succeeds there must be a last element (which @@ -2349,6 +2360,7 @@ impl Vec { self.buf.grow_one(); } + // SAFETY: Untriaged. unsafe { // infallible // The spot to put the new value @@ -2435,6 +2447,7 @@ impl Vec { if index >= len { return None; } + // SAFETY: Untriaged. unsafe { // infallible let ret; @@ -2682,6 +2695,7 @@ impl Vec { let mut first_duplicate_idx: usize = 1; let start = self.as_mut_ptr(); while first_duplicate_idx != len { + // SAFETY: Untriaged. let found_duplicate = unsafe { // SAFETY: first_duplicate always in range [1..len) // Note that we start iteration from 1 so we never overflow. @@ -2721,6 +2735,7 @@ impl Vec { /* SAFETY: invariant guarantees that `read - write` * and `len - read` never overflow and that the copy is always * in-bounds. */ + // SAFETY: Untriaged. unsafe { let ptr = self.vec.as_mut_ptr(); let len = self.vec.len(); @@ -2753,6 +2768,7 @@ impl Vec { // Construct gap first and then drop item to avoid memory corruption if `T::drop` panics. let mut gap = FillGapOnDrop { read: first_duplicate_idx + 1, write: first_duplicate_idx, vec: self }; + // SAFETY: Untriaged. unsafe { // SAFETY: we checked that first_duplicate_idx in bounds before. // If drop panics, `gap` would remove this item without drop. @@ -2761,6 +2777,7 @@ impl Vec { /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr * are always in-bounds and read_ptr never aliases prev_ptr */ + // SAFETY: Untriaged. unsafe { while gap.read < len { let read_ptr = start.add(gap.read); @@ -2837,6 +2854,7 @@ impl Vec { return Err(value); } + // SAFETY: Untriaged. unsafe { let end = self.as_mut_ptr().add(self.len); ptr::write(end, value); @@ -2873,6 +2891,7 @@ impl Vec { if self.len == 0 { None } else { + // SAFETY: Untriaged. unsafe { self.len -= 1; core::hint::assert_unchecked(self.len < self.capacity()); @@ -2947,6 +2966,7 @@ impl Vec { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { + // SAFETY: Untriaged. unsafe { self.append_elements(other.as_slice() as _); other.set_len(0); @@ -2958,6 +2978,7 @@ impl Vec { #[inline] unsafe fn append_elements(&mut self, other: *const [T]) { self.reserve(other.len()); + // SAFETY: Untriaged. unsafe { self.append_elements_unreserved(other); } @@ -2967,6 +2988,7 @@ impl Vec { #[inline] unsafe fn try_append_elements(&mut self, other: *const [T]) -> Result<(), TryReserveError> { self.try_reserve(other.len())?; + // SAFETY: Untriaged. unsafe { self.append_elements_unreserved(other); } @@ -2979,6 +3001,7 @@ impl Vec { let count = other.len(); let len = self.len(); if count > 0 { + // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; @@ -3036,6 +3059,7 @@ impl Vec { let len = self.len(); let Range { start, end } = slice::range(range, ..len); + // SAFETY: Untriaged. unsafe { // set self.vec length's to start, to be safe in case Drain is leaked self.set_len(start); @@ -3175,6 +3199,7 @@ impl Vec { let mut other = Vec::with_capacity_in(other_len, self.allocator().clone()); // Unsafely `set_len` and copy items to `other`. + // SAFETY: Untriaged. unsafe { self.set_len(at); other.set_len(other_len); @@ -3263,6 +3288,7 @@ impl Vec { A: 'a, { let mut me = ManuallyDrop::new(self); + // SAFETY: Untriaged. unsafe { slice::from_raw_parts_mut(me.as_mut_ptr(), me.len) } } @@ -3301,6 +3327,7 @@ impl Vec { // Note: // This method is not implemented in terms of `split_at_spare_mut`, // to prevent invalidation of pointers to the buffer. + // SAFETY: Untriaged. unsafe { slice::from_raw_parts_mut( self.as_mut_ptr().add(self.len) as *mut MaybeUninit, @@ -3660,6 +3687,7 @@ impl Vec { &mut self, other: &[u8], ) -> Result<(), TryReserveError> { + // SAFETY: Untriaged. unsafe { self.try_append_elements(other) } } } @@ -3713,6 +3741,7 @@ impl Vec { fn extend_with(&mut self, n: usize, value: T) { self.reserve(n); + // SAFETY: Untriaged. unsafe { let mut ptr = self.as_mut_ptr().add(self.len()); // Use SetLenOnDrop to work around bug where compiler @@ -4020,6 +4049,7 @@ impl IntoIterator for Vec { /// ``` #[inline] fn into_iter(self) -> Self::IntoIter { + // SAFETY: Untriaged. unsafe { let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); @@ -4103,6 +4133,7 @@ impl Vec { let (lower, _) = iterator.size_hint(); self.reserve(lower.saturating_add(1)); } + // SAFETY: Untriaged. unsafe { ptr::write(self.as_mut_ptr().add(len), element); // Since next() executes user code which can panic we have to bump the length @@ -4126,6 +4157,7 @@ impl Vec { (low, high) ); self.reserve(additional); + // SAFETY: Untriaged. unsafe { let ptr = self.as_mut_ptr(); let mut local_len = SetLenOnDrop::new(&mut self.len); @@ -4351,6 +4383,7 @@ const unsafe impl<#[may_dangle] T: [const] Destruct, A: [const] Allocator + [con for Vec { fn drop(&mut self) { + // SAFETY: Untriaged. unsafe { // use drop for [T] // use a raw slice to refer to the elements of the vector as weakest necessary type; diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs index b3fee7d094e20..320342b2fc898 100644 --- a/library/alloc/src/vec/spec_extend.rs +++ b/library/alloc/src/vec/spec_extend.rs @@ -30,6 +30,7 @@ where impl SpecExtend> for Vec { fn spec_extend(&mut self, iterator: IntoIter) { + // SAFETY: Untriaged. unsafe { self.append_elements(iterator.as_slice() as _); } @@ -53,6 +54,7 @@ where { fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) { let slice = iterator.as_slice(); + // SAFETY: Untriaged. unsafe { self.append_elements(slice) }; } } diff --git a/library/alloc/src/vec/spec_from_elem.rs b/library/alloc/src/vec/spec_from_elem.rs index 96d701e15d487..68558cc380832 100644 --- a/library/alloc/src/vec/spec_from_elem.rs +++ b/library/alloc/src/vec/spec_from_elem.rs @@ -36,6 +36,7 @@ impl SpecFromElem for i8 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } let mut v = Vec::with_capacity_in(n, alloc); + // SAFETY: Untriaged. unsafe { ptr::write_bytes(v.as_mut_ptr(), elem as u8, n); v.set_len(n); @@ -51,6 +52,7 @@ impl SpecFromElem for u8 { return Vec { buf: RawVec::with_capacity_zeroed_in(n, alloc), len: n }; } let mut v = Vec::with_capacity_in(n, alloc); + // SAFETY: Untriaged. unsafe { ptr::write_bytes(v.as_mut_ptr(), elem, n); v.set_len(n); diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs index ccbc2936fb4e8..c8cda1de9169c 100644 --- a/library/alloc/src/vec/spec_from_iter.rs +++ b/library/alloc/src/vec/spec_from_iter.rs @@ -46,6 +46,7 @@ impl SpecFromIter> for Vec { // But it is a conservative choice. let has_advanced = iterator.buf != iterator.ptr; if !has_advanced || iterator.len() >= iterator.cap / 2 { + // SAFETY: Untriaged. unsafe { let it = ManuallyDrop::new(iterator); if has_advanced { diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index 77f7761d22f95..5a078f36aeb8c 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -28,6 +28,7 @@ where let initial_capacity = cmp::max(RawVec::::MIN_NON_ZERO_CAP, lower.saturating_add(1)); let mut vector = Vec::with_capacity(initial_capacity); + // SAFETY: Untriaged. unsafe { // SAFETY: We requested capacity at least 1 ptr::write(vector.as_mut_ptr(), element); diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 99ebcb4ada296..33b08be9423be 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -61,6 +61,7 @@ impl Drop for Splice<'_, I, A> { // the ptr.offset_from_unsigned contract. self.drain.iter = (&[]).iter(); + // SAFETY: Untriaged. unsafe { if self.drain.tail_len == 0 { self.drain.vec.as_mut().extend(self.replace_with.by_ref()); @@ -104,6 +105,7 @@ impl Drain<'_, T, A> { /// Fill that range as much as possible with new elements from the `replace_with` iterator. /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { + // SAFETY: Untriaged. let vec = unsafe { self.vec.as_mut() }; let range_start = vec.len; let range_end = self.tail_start; @@ -113,6 +115,7 @@ impl Drain<'_, T, A> { let Some(new_item) = replace_with.next() else { return false; }; + // SAFETY: Untriaged. unsafe { vec.as_mut_ptr().add(idx).write(new_item) }; vec.len += 1; } @@ -121,11 +124,13 @@ impl Drain<'_, T, A> { /// Makes room for inserting more elements before the tail. unsafe fn move_tail(&mut self, additional: usize) { + // SAFETY: Untriaged. let vec = unsafe { self.vec.as_mut() }; let len = self.tail_start + self.tail_len; vec.buf.reserve(len, additional); let new_tail_start = self.tail_start + additional; + // SAFETY: Untriaged. unsafe { let src = vec.as_ptr().add(self.tail_start); let dst = vec.as_mut_ptr().add(new_tail_start); diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs index 394c41bf36727..481d648435127 100644 --- a/library/alloc/src/wtf8/mod.rs +++ b/library/alloc/src/wtf8/mod.rs @@ -148,11 +148,13 @@ impl Wtf8Buf { Err(surrogate) => { let surrogate = surrogate.unpaired_surrogate(); // Surrogates are known to be in the code point range. + // SAFETY: Untriaged. let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; // The string will now contain an unpaired surrogate. string.is_known_utf8 = false; // Skip the WTF-8 concatenation check, // surrogate pairs are already decoded by decode_utf16 + // SAFETY: Untriaged. unsafe { string.push_code_point_unchecked(code_point); } @@ -173,6 +175,7 @@ impl Wtf8Buf { #[inline] pub fn as_slice(&self) -> &Wtf8 { + // SAFETY: Untriaged. unsafe { Wtf8::from_bytes_unchecked(&self.bytes) } } @@ -181,6 +184,7 @@ impl Wtf8Buf { // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would // cause them to change from well-formed UTF-8 to ill-formed UTF-8, // which would break the assumptions of the `is_known_utf8` field. + // SAFETY: Untriaged. unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) } } @@ -262,6 +266,7 @@ impl Wtf8Buf { #[inline] pub fn leak<'a>(self) -> &'a mut Wtf8 { + // SAFETY: Untriaged. unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) } } @@ -337,6 +342,7 @@ impl Wtf8Buf { } // No newly paired surrogates at the boundary. + // SAFETY: Untriaged. unsafe { self.push_code_point_unchecked(code_point) } } @@ -371,6 +377,7 @@ impl Wtf8Buf { /// the original WTF-8 string is returned instead. pub fn into_string(self) -> Result { if self.is_known_utf8 || self.next_surrogate(0).is_none() { + // SAFETY: Untriaged. Ok(unsafe { String::from_utf8_unchecked(self.bytes) }) } else { Err(self) @@ -392,6 +399,7 @@ impl Wtf8Buf { self.bytes[surrogate_pos..pos].copy_from_slice("\u{FFFD}".as_bytes()); } } + // SAFETY: Untriaged. unsafe { String::from_utf8_unchecked(self.bytes) } } @@ -404,6 +412,7 @@ impl Wtf8Buf { /// Converts a `Box` into a `Wtf8Buf`. pub fn from_box(boxed: Box) -> Wtf8Buf { + // SAFETY: Untriaged. let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) }; Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false } } @@ -468,6 +477,7 @@ pub(super) fn to_owned(slice: &Wtf8) -> Wtf8Buf { /// This only copies the data if necessary (if it contains any surrogate). pub(super) fn to_string_lossy(slice: &Wtf8) -> Cow<'_, str> { let Some((surrogate_pos, _)) = slice.next_surrogate(0) else { + // SAFETY: Untriaged. return Cow::Borrowed(unsafe { str::from_utf8_unchecked(slice.as_bytes()) }); }; let wtf8_bytes = slice.as_bytes(); @@ -484,6 +494,7 @@ pub(super) fn to_string_lossy(slice: &Wtf8) -> Cow<'_, str> { } None => { utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]); + // SAFETY: Untriaged. return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) }); } } @@ -516,12 +527,14 @@ impl Wtf8 { #[rustc_allow_incoherent_impl] pub fn into_box(&self) -> Box { let boxed: Box<[u8]> = self.as_bytes().into(); + // SAFETY: Untriaged. unsafe { mem::transmute(boxed) } } #[rustc_allow_incoherent_impl] pub fn empty_box() -> Box { let boxed: Box<[u8]> = Default::default(); + // SAFETY: Untriaged. unsafe { mem::transmute(boxed) } } @@ -529,12 +542,14 @@ impl Wtf8 { #[rustc_allow_incoherent_impl] pub fn into_arc(&self) -> Arc { let arc: Arc<[u8]> = Arc::from(self.as_bytes()); + // SAFETY: Untriaged. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) } } #[rustc_allow_incoherent_impl] pub fn into_rc(&self) -> Rc { let rc: Rc<[u8]> = Rc::from(self.as_bytes()); + // SAFETY: Untriaged. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) } } @@ -554,6 +569,7 @@ impl Wtf8 { #[inline] fn decode_surrogate_pair(lead: u16, trail: u16) -> char { let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32); + // SAFETY: Untriaged. unsafe { char::from_u32_unchecked(code_point) } } From 0de0b1d3c7b1fcd6e5098ad8b36eb4964d560e05 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 11 Aug 2026 20:05:59 +0200 Subject: [PATCH 3/8] fixup! tidy: enforce documented unsafe --- src/tools/tidy/src/style.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index e779577ad8f07..4db2c48e833ae 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -522,15 +522,17 @@ fn check_file_style(check: &mut RunningCheck, file: &Path, contents: &str) { err("Don't use magic numbers that spell things (consider 0x12345678)"); } } - // Only check library crates. + // Only check core & alloc for now; to be expanded to (parts of) + // std in the future as well. if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment + && !is_test && file.components().any(|c| { let c = c.as_os_str(); - c == "core" || c == "alloc" || c == "std" + c == "core" || c == "alloc" }) - && !is_test + && !file.components().any(|c| c.as_os_str() == "std") { suppressible_tidy_err!(err, ignore.undocumented_unsafe, "undocumented unsafe"); } From e6411db3b21f9cde55eb264294e2babd2d4361cb Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Tue, 11 Aug 2026 22:27:18 +0200 Subject: [PATCH 4/8] this was pain and it's not even half i think --- library/alloc/src/alloc.rs | 16 +-- library/alloc/src/boxed.rs | 54 +++++------ library/alloc/src/boxed/convert.rs | 31 +++--- library/alloc/src/boxed/thin.rs | 20 ++-- .../alloc/src/collections/binary_heap/mod.rs | 19 ++-- library/alloc/src/collections/btree/map.rs | 22 ++--- library/alloc/src/collections/btree/mem.rs | 4 +- .../alloc/src/collections/btree/navigate.rs | 18 ++-- library/alloc/src/collections/btree/node.rs | 3 +- library/alloc/src/collections/btree/search.rs | 2 +- library/alloc/src/collections/btree/set.rs | 8 +- library/alloc/src/collections/linked_list.rs | 28 +++--- .../alloc/src/collections/vec_deque/drain.rs | 7 +- .../src/collections/vec_deque/extract_if.rs | 3 +- .../alloc/src/collections/vec_deque/iter.rs | 3 +- .../src/collections/vec_deque/iter_mut.rs | 3 +- .../alloc/src/collections/vec_deque/mod.rs | 59 +++++------ .../src/collections/vec_deque/spec_extend.rs | 8 +- .../alloc/src/collections/vec_deque/splice.rs | 2 +- library/alloc/src/ffi/c_str.rs | 33 +++---- library/alloc/src/io/cursor.rs | 8 +- library/alloc/src/io/error.rs | 7 +- library/alloc/src/io/read.rs | 2 +- library/alloc/src/io/util.rs | 3 +- library/alloc/src/raw_vec/mod.rs | 28 +++--- library/alloc/src/rc.rs | 66 ++++++------- library/alloc/src/slice.rs | 7 +- library/alloc/src/str.rs | 4 +- library/alloc/src/string.rs | 5 +- library/alloc/src/sync.rs | 97 +++++++++---------- library/alloc/src/vec/drain.rs | 2 +- library/alloc/src/vec/extract_if.rs | 9 +- library/alloc/src/vec/in_place_collect.rs | 3 +- library/alloc/src/vec/into_iter.rs | 34 +++---- library/alloc/src/vec/is_zero.rs | 2 +- library/alloc/src/vec/mod.rs | 29 +++--- .../alloc/src/vec/spec_from_iter_nested.rs | 3 +- library/alloc/src/vec/splice.rs | 4 +- library/alloc/src/wtf8/mod.rs | 10 +- 39 files changed, 296 insertions(+), 370 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 2cdf4ca003c49..f4445c501d45d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -116,7 +116,7 @@ pub struct Global; #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc(layout: Layout) -> *mut u8 { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { // Make sure we don't accidentally allow omitting the allocator shim in // stable code until it is actually stabilized. @@ -160,7 +160,7 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { dealloc_nonnull(NonNull::new_unchecked(ptr), layout) } } @@ -168,7 +168,7 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn dealloc_nonnull(ptr: NonNull, layout: Layout) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { __rust_dealloc(ptr, layout.size(), layout.alignment()) } } @@ -215,7 +215,7 @@ unsafe fn dealloc_nonnull(ptr: NonNull, layout: Layout) { #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { realloc_nonnull(NonNull::new_unchecked(ptr), layout, new_size) } } @@ -223,7 +223,7 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces unsafe fn realloc_nonnull(ptr: NonNull, layout: Layout, new_size: usize) -> *mut u8 { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { __rust_realloc(ptr, layout.size(), layout.alignment(), new_size) } } @@ -281,7 +281,7 @@ unsafe fn realloc_nonnull(ptr: NonNull, layout: Layout, new_size: usize) -> #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { // Make sure we don't accidentally allow omitting the allocator shim in // stable code until it is actually stabilized. @@ -525,7 +525,7 @@ impl Global { cmp::min(old_layout.size(), new_layout.size()), ); } - // SAFETY: Untriaged. + // SAFETY: Caller ensures the ptr & layout are correct. unsafe { self.deallocate_impl(ptr, old_layout); } @@ -640,7 +640,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { #[inline] fn rt_error(layout: Layout) -> ! { - // SAFETY: Untriaged. + // SAFETY: Safe to call; we control this function. unsafe { __rust_alloc_error_handler(layout.size(), layout.align()); } diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bb4537cb64888..67ca0b0870d1d 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -266,7 +266,8 @@ const fn box_new_uninit(layout: Layout) -> *mut u8 { pub const fn box_assume_init_into_vec_unsafe( b: Box>, ) -> crate::vec::Vec { - // SAFETY: Untriaged. + // SAFETY: Technically not, but this can't be + // called stably except in ways we control. unsafe { (b.assume_init() as Box<[T]>).into_vec() } } @@ -531,7 +532,7 @@ impl Box { { let mut boxed = Self::new_uninit_in(alloc); boxed.write(x); - // SAFETY: Untriaged. + // SAFETY: Initialised by the above. unsafe { boxed.assume_init() } } @@ -558,7 +559,7 @@ impl Box { { let mut boxed = Self::try_new_uninit_in(alloc)?; boxed.write(x); - // SAFETY: Untriaged. + // SAFETY: Initialised by the above. unsafe { Ok(boxed.assume_init()) } } @@ -623,7 +624,7 @@ impl Box { let layout = Layout::new::>(); alloc.allocate(layout)?.cast() }; - // SAFETY: Untriaged. + // SAFETY: Pointer is nonnull and matches the allocator. unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } } @@ -696,7 +697,7 @@ impl Box { let layout = Layout::new::>(); alloc.allocate_zeroed(layout)?.cast() }; - // SAFETY: Untriaged. + // SAFETY: Pointer is nonnull and matches the allocator. unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } } @@ -733,7 +734,7 @@ impl Box { #[unstable(feature = "box_into_boxed_slice", issue = "71582")] pub fn into_boxed_slice(boxed: Self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(boxed); - // SAFETY: Untriaged. + // SAFETY: A pointer to T is also a valid pointer to [T; 1]. unsafe { Box::from_raw_in(raw as *mut [T; 1], alloc) } } @@ -777,7 +778,8 @@ impl Box { /// ``` #[unstable(feature = "box_take", issue = "147212")] pub fn take(boxed: Self) -> (T, Box, A>) { - // SAFETY: Untriaged. + // SAFETY: Reading out an initialised value & leaving behind a + // box with uninit contents. unsafe { let (raw, alloc) = Box::into_non_null_with_allocator(boxed); let value = raw.read(); @@ -881,8 +883,7 @@ impl Box { impl<'a, A: Allocator> Drop for DeallocDropGuard<'a, A> { fn drop(&mut self) { let &mut DeallocDropGuard(layout, alloc, ptr) = self; - // Safety: `ptr` was allocated by `*alloc` with layout `layout` - // SAFETY: Untriaged. + // SAFETY: `ptr` was allocated by `*alloc` with layout `layout` unsafe { alloc.deallocate(ptr, layout); } @@ -897,17 +898,15 @@ impl Box { (ptr, Some(DeallocDropGuard(layout, &alloc, ptr))) }; let ptr = ptr.as_ptr(); - // Safety: `*ptr` is newly allocated, correctly aligned to `align_of_val(src)`, + // SAFETY: `*ptr` is newly allocated, correctly aligned to `align_of_val(src)`, // and is valid for writes for `size_of_val(src)`. // If this panics, then `guard` will deallocate for us (if allocation occuured) - // SAFETY: Untriaged. unsafe { ::clone_to_uninit(src, ptr); } // Defuse the deallocate guard core::mem::forget(guard); - // Safety: We just initialized `*ptr` as a clone of `src` - // SAFETY: Untriaged. + // SAFETY: We just initialized `*ptr` as a clone of `src` Ok(unsafe { Box::from_raw_in(ptr.with_metadata_of(src), alloc) }) } } @@ -1257,7 +1256,7 @@ impl Box, A> { #[stable(feature = "box_uninit_write", since = "1.87.0")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box { - // SAFETY: Untriaged. + // SAFETY: Writing initialises the boxed value. unsafe { (*boxed).write(value); boxed.assume_init() @@ -1294,7 +1293,7 @@ impl Box<[mem::MaybeUninit], A> { #[inline] pub unsafe fn assume_init(self) -> Box<[T], A> { let (raw, alloc) = Box::into_raw_with_allocator(self); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Box::from_raw_in(raw as *mut [T], alloc) } } } @@ -1348,7 +1347,7 @@ impl Box { #[inline] #[must_use = "call `drop(Box::from_raw(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_raw(raw: *mut T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_raw_in(raw, Global) } } @@ -1401,7 +1400,7 @@ impl Box { #[inline] #[must_use = "call `drop(Box::from_non_null(ptr))` if you intend to drop the `Box`"] pub unsafe fn from_non_null(ptr: NonNull) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_raw(ptr.as_ptr()) } } @@ -1581,7 +1580,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. Box(unsafe { Unique::new_unchecked(raw) }, alloc) } @@ -1700,7 +1699,7 @@ impl Box { // In case `A` *is* `Global`, this does not quite have the right behavior; `into_raw` // works around that. let ptr = &raw mut **b; - // SAFETY: Untriaged. + // SAFETY: See above. let alloc = unsafe { ptr::read(&b.1) }; (ptr, alloc) } @@ -1768,7 +1767,7 @@ impl Box { #[doc(hidden)] pub fn into_unique(b: Self) -> (Unique, A) { let (ptr, alloc) = Box::into_raw_with_allocator(b); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid and unique. unsafe { (Unique::from(&mut *ptr), alloc) } } @@ -1967,7 +1966,7 @@ impl Box { { let (ptr, alloc) = Box::into_raw_with_allocator(b); mem::forget(alloc); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid and unique. unsafe { &mut *ptr } } @@ -2006,10 +2005,9 @@ impl Box { where A: 'static, { - // It's not possible to move or replace the insides of a `Pin>` - // when `T: !Unpin`, so it's safe to pin it directly without any - // additional requirements. - // SAFETY: Untriaged. + // SAFETY: It's not possible to move or replace the insides of a + // `Pin>` when `T: !Unpin`, so it's safe to pin it directly + // without any additional requirements. unsafe { Pin::new_unchecked(boxed) } } } @@ -2039,7 +2037,7 @@ impl Default for Box { #[inline] fn default() -> Self { let mut x: Box> = Box::new_uninit(); - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: `x` is valid for writing and has the same layout as `T`. // If `T::default()` panics, dropping `x` will just deallocate the Box as `MaybeUninit` @@ -2115,7 +2113,7 @@ impl Clone for Box { fn clone(&self) -> Self { // Pre-allocate memory to allow writing the cloned value directly. let mut boxed = Self::new_uninit_in(self.1.clone()); - // SAFETY: Untriaged. + // SAFETY: Destination pointer is valid and will then become initialised. unsafe { (**self).clone_to_uninit(boxed.as_mut_ptr().cast()); boxed.assume_init() @@ -2186,7 +2184,7 @@ impl Clone for Box { fn clone(&self) -> Self { // this makes a copy of the data let buf: Box<[u8]> = self.as_bytes().into(); - // SAFETY: Untriaged. + // SAFETY: We know the [u8] is a valid str. unsafe { from_boxed_utf8_unchecked(buf) } } } diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index 4ab9a796297c6..692f01c21e438 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -217,7 +217,7 @@ impl From> for Box<[u8], A> { #[inline] fn from(s: Box) -> Self { let (raw, alloc) = Box::into_raw_with_allocator(s); - // SAFETY: Untriaged. + // SAFETY: All `str`s are also valid if reinterpreted as `[u8]`s. unsafe { Box::from_raw_in(raw as *mut [u8], alloc) } } } @@ -271,7 +271,7 @@ impl TryFrom> for Box<[T; N]> { /// `boxed_slice.len()` does not equal `N`. fn try_from(boxed_slice: Box<[T]>) -> Result { if boxed_slice.len() == N { - // SAFETY: Untriaged. + // SAFETY: Checked length. Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) } else { Err(boxed_slice) @@ -305,7 +305,7 @@ impl TryFrom> for Box<[T; N]> { fn try_from(vec: Vec) -> Result { if vec.len() == N { let boxed_slice = vec.into_boxed_slice(); - // SAFETY: Untriaged. + // SAFETY: Checked length. Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) } else { Err(vec) @@ -334,7 +334,7 @@ impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { - // SAFETY: Untriaged. + // SAFETY: Check ensures the type is correct. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -366,7 +366,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); - // SAFETY: Untriaged. + // SAFETY: Caller ensures the type is correct. unsafe { let (raw, alloc): (*mut dyn Any, _) = Box::into_raw_with_allocator(self); Box::from_raw_in(raw as *mut T, alloc) @@ -395,7 +395,7 @@ impl Box { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn downcast(self) -> Result, Self> { - // SAFETY: Untriaged. + // SAFETY: Check ensures the type is correct. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -427,7 +427,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); - // SAFETY: Untriaged. + // SAFETY: Caller ensures the type is correct. unsafe { let (raw, alloc): (*mut (dyn Any + Send), _) = Box::into_raw_with_allocator(self); Box::from_raw_in(raw as *mut T, alloc) @@ -456,7 +456,7 @@ impl Box { #[inline] #[stable(feature = "box_send_sync_any_downcast", since = "1.51.0")] pub fn downcast(self) -> Result, Self> { - // SAFETY: Untriaged. + // SAFETY: Check ensures the type is correct. if self.is::() { unsafe { Ok(self.downcast_unchecked::()) } } else { Err(self) } } @@ -488,7 +488,7 @@ impl Box { #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Box { debug_assert!(self.is::()); - // SAFETY: Untriaged. + // SAFETY: Caller ensures the type is correct. unsafe { let (raw, alloc): (*mut (dyn Any + Send + Sync), _) = Box::into_raw_with_allocator(self); @@ -718,7 +718,7 @@ impl dyn Error { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { if self.is::() { - // SAFETY: Untriaged. + // SAFETY: Check ensures the type is correct. unsafe { let raw: *mut dyn Error = Box::into_raw(self); Ok(Box::from_raw(raw as *mut T)) @@ -736,11 +736,9 @@ impl dyn Error + Send { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; - // SAFETY: Untriaged. - ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send` marker. - mem::transmute::, Box>(s) - }) + ::downcast(err) + // SAFETY: Reapplying the `Send` marker we already know to hold. + .map_err(|s| unsafe { mem::transmute::, Box>(s) }) } } @@ -751,9 +749,8 @@ impl dyn Error + Send + Sync { #[rustc_allow_incoherent_impl] pub fn downcast(self: Box) -> Result, Box> { let err: Box = self; - // SAFETY: Untriaged. + // SAFETY: Reapplying the `Send` and `Sync` markers we already know to hold. ::downcast(err).map_err(|s| unsafe { - // Reapply the `Send + Sync` markers. mem::transmute::, Box>(s) }) } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index 44d3eeee89d78..d3f9bbd791fd3 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -146,7 +146,7 @@ impl Deref for ThinBox { let value = self.data(); let metadata = self.meta(); let pointer = ptr::from_raw_parts(value as *const (), metadata); - // SAFETY: Untriaged. + // SAFETY: &ThinBox is also a valid pointer for T. unsafe { &*pointer } } } @@ -157,7 +157,7 @@ impl DerefMut for ThinBox { let value = self.data(); let metadata = self.meta(); let pointer = ptr::from_raw_parts_mut::(value as *mut (), metadata); - // SAFETY: Untriaged. + // SAFETY: &mut ThinBox is also a valid pointer for T. unsafe { &mut *pointer } } } @@ -177,9 +177,7 @@ impl Drop for ThinBox { #[unstable(feature = "thin_box", issue = "92791")] impl ThinBox { fn meta(&self) -> ::Metadata { - // Safety: - // - NonNull and valid. - // SAFETY: Untriaged. + // SAFETY: NonNull and valid. unsafe { *self.with_header().header() } } @@ -336,7 +334,7 @@ impl WithHeader { let alloc_size = max(align_of::(), size_of::<::Metadata>()); - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: align is power of two because it is the maximum of two alignments. let alloc: *mut u8 = const_allocate(alloc_size, alloc_align); @@ -355,9 +353,8 @@ impl WithHeader { } }; - // SAFETY: `alloc` points to `::Metadata`, so addition stays in-bounds. let value_ptr = -// SAFETY: Untriaged. + // SAFETY: `alloc` points to `::Metadata`, so addition stays in-bounds. unsafe { (alloc as *const ::Metadata).add(1) }.cast::().cast_mut(); debug_assert!(value_ptr.is_aligned()); mem::forget(value); @@ -381,7 +378,7 @@ impl WithHeader { return; } - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: Layout must have been computable if we're in drop let (layout, value_offset) = @@ -394,7 +391,7 @@ impl WithHeader { } } - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. let _guard = DropGuard { @@ -410,14 +407,13 @@ impl WithHeader { } fn header(&self) -> *mut H { - // Safety: + // SAFETY: // - At least `size_of::()` bytes are allocated ahead of the pointer. // - We know that H will be aligned because the middle pointer is aligned to the greater // of the alignment of the header and the data and the header size includes the padding // needed to align the header. Subtracting the header size from the aligned data pointer // will always result in an aligned header pointer, it just may not point to the // beginning of the allocation. - // SAFETY: Untriaged. let hp = unsafe { self.0.as_ptr().sub(Self::header_size()) as *mut H }; debug_assert!(hp.is_aligned()); hp diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 8f6435299bdb3..2666d70d4df28 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -326,8 +326,7 @@ impl Deref for PeekMut<'_, T, A> { type Target = T; fn deref(&self) -> &T { debug_assert!(!self.heap.is_empty()); - // SAFE: PeekMut is only instantiated for non-empty heaps - // SAFETY: Untriaged. + // SAFETY: PeekMut is only instantiated for non-empty heaps unsafe { self.heap.data.get_unchecked(0) } } } @@ -347,7 +346,7 @@ impl DerefMut for PeekMut<'_, T, A> { // // This is technique is described throughout several other places in // the standard library as "leak amplification". - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: len > 1 so len != 0. self.original_len = Some(NonZero::new_unchecked(len)); @@ -357,8 +356,7 @@ impl DerefMut for PeekMut<'_, T, A> { } } - // SAFE: PeekMut is only instantiated for non-empty heaps - // SAFETY: Untriaged. + // SAFETY: PeekMut is only instantiated for non-empty heaps unsafe { self.heap.data.get_unchecked_mut(0) } } } @@ -1539,8 +1537,7 @@ impl<'a, T> Hole<'a, T> { #[inline] unsafe fn new(data: &'a mut [T], pos: usize) -> Self { debug_assert!(pos < data.len()); - // SAFE: pos should be inside the slice - // SAFETY: Untriaged. + // SAFETY: pos should be inside the slice let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; Hole { data, elt: ManuallyDrop::new(elt), pos } } @@ -1558,18 +1555,20 @@ impl<'a, T> Hole<'a, T> { /// Returns a reference to the element at `index`. /// - /// Unsafe because index must be within the data slice and not equal to pos. + /// # Safety + /// `index` must be within the data slice and not equal to the current position. #[inline] unsafe fn get(&self, index: usize) -> &T { debug_assert!(index != self.pos); debug_assert!(index < self.data.len()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.data.get_unchecked(index) } } /// Move hole to new location /// - /// Unsafe because index must be within the data slice and not equal to pos. + /// # Safety + /// `index` must be within the data slice and not equal to the current position. #[inline] unsafe fn move_to(&mut self, index: usize) { debug_assert!(index != self.pos); diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 291b3dd42170a..fd04bce4cdd8a 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1322,11 +1322,10 @@ impl BTreeMap { // this through using a drop handler and transmutating CursorMutKey // to CursorMutKey, ManuallyDrop> (see PR #152418) if let Some((k, v)) = self_cursor.remove_next() { + let v = conflict(&k, v, first_other_val); // SAFETY: we remove the K, V out of the next entry, // apply 'f' to get a new (K, V), and insert it back // into the next entry that the cursor is pointing at - let v = conflict(&k, v, first_other_val); - // SAFETY: Untriaged. unsafe { self_cursor.insert_after_unchecked(k, v) }; } } @@ -1359,11 +1358,10 @@ impl BTreeMap { // this through using a drop handler and transmutating CursorMutKey // to CursorMutKey, ManuallyDrop> (see PR #152418) if let Some((k, v)) = self_cursor.remove_next() { + let v = conflict(&k, v, other_val); // SAFETY: we remove the K, V out of the next entry, // apply 'f' to get a new (K, V), and insert it back // into the next entry that the cursor is pointing at - let v = conflict(&k, v, other_val); - // SAFETY: Untriaged. unsafe { self_cursor.insert_after_unchecked(k, v) }; } break; @@ -1741,7 +1739,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { None } else { self.length -= 1; - // SAFETY: Untriaged. + // SAFETY: Ensured by check. Some(unsafe { self.range.next_unchecked() }) } } @@ -1779,7 +1777,7 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { None } else { self.length -= 1; - // SAFETY: Untriaged. + // SAFETY: Ensured by check. Some(unsafe { self.range.next_back_unchecked() }) } } @@ -1821,7 +1819,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { None } else { self.length -= 1; - // SAFETY: Untriaged. + // SAFETY: Ensured by check. Some(unsafe { self.range.next_unchecked() }) } } @@ -1856,7 +1854,7 @@ impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { None } else { self.length -= 1; - // SAFETY: Untriaged. + // SAFETY: Ensured by check. Some(unsafe { self.range.next_back_unchecked() }) } } @@ -3548,7 +3546,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { return Err(UnorderedKeyError {}); } } - // SAFETY: Untriaged. + // SAFETY: Ensured by checks above. unsafe { self.insert_after_unchecked(key, value); } @@ -3577,7 +3575,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { return Err(UnorderedKeyError {}); } } - // SAFETY: Untriaged. + // SAFETY: Ensured by checks above. unsafe { self.insert_before_unchecked(key, value); } @@ -3659,7 +3657,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { /// * All keys in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, key: K, value: V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_after_unchecked(key, value) } } @@ -3678,7 +3676,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> { /// * All keys in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, key: K, value: V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_before_unchecked(key, value) } } diff --git a/library/alloc/src/collections/btree/mem.rs b/library/alloc/src/collections/btree/mem.rs index 674083ac6ae09..a0e9e173757a0 100644 --- a/library/alloc/src/collections/btree/mem.rs +++ b/library/alloc/src/collections/btree/mem.rs @@ -23,10 +23,10 @@ pub(super) fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { } } let guard = PanicGuard; - // SAFETY: Untriaged. + // SAFETY: v is valid for reads. let value = unsafe { ptr::read(v) }; let (new_value, ret) = change(value); - // SAFETY: Untriaged. + // SAFETY: new_value is T and v is valid for writes. unsafe { ptr::write(v, new_value); } diff --git a/library/alloc/src/collections/btree/navigate.rs b/library/alloc/src/collections/btree/navigate.rs index 880507928d72a..30cc8218908da 100644 --- a/library/alloc/src/collections/btree/navigate.rs +++ b/library/alloc/src/collections/btree/navigate.rs @@ -160,13 +160,13 @@ impl LazyLeafRange { impl<'a, K, V> LazyLeafRange, K, V> { #[inline] pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.init_front().unwrap().next_unchecked() } } #[inline] pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.init_back().unwrap().next_back_unchecked() } } } @@ -174,13 +174,13 @@ impl<'a, K, V> LazyLeafRange, K, V> { impl<'a, K, V> LazyLeafRange, K, V> { #[inline] pub(super) unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.init_front().unwrap().next_unchecked() } } #[inline] pub(super) unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.init_back().unwrap().next_back_unchecked() } } } @@ -365,9 +365,8 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> /// The results are non-unique references allowing mutation (of values only), so must be used /// with care. pub(super) fn full_range(self) -> LazyLeafRange, K, V> { - // We duplicate the root NodeRef here -- we will never visit the same KV - // twice, and never end up with overlapping value references. - // SAFETY: Untriaged. + // SAFETY: We duplicate the root NodeRef here -- we will never visit the + // same KV twice, and never end up with overlapping value references. let self2 = unsafe { ptr::read(&self) }; full_range(self, self2) } @@ -378,9 +377,8 @@ impl NodeRef { /// The results are non-unique references allowing massively destructive mutation, so must be /// used with the utmost care. pub(super) fn full_range(self) -> LazyLeafRange { - // We duplicate the root NodeRef here -- we will never access it in a way - // that overlaps references obtained from the root. - // SAFETY: Untriaged. + // SAFETY: We duplicate the root NodeRef here -- we will never access + // it in a way that overlaps references obtained from the root. let self2 = unsafe { ptr::read(&self) }; full_range(self, self2) } diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 6ba7042b389ad..e9957b8e5ae66 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -290,9 +290,8 @@ impl NodeRef { /// Note that, despite being safe, calling this function can have the side effect /// of invalidating mutable references that unsafe code has created. pub(super) fn len(&self) -> usize { - // Crucially, we only access the `len` field here. If BorrowType is marker::ValMut, + // SAFETY: We only access the `len` field here. If BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. - // SAFETY: Untriaged. unsafe { usize::from((*Self::as_leaf_ptr(self)).len) } } diff --git a/library/alloc/src/collections/btree/search.rs b/library/alloc/src/collections/btree/search.rs index ebc61a2dc0b18..bc7e0fff72500 100644 --- a/library/alloc/src/collections/btree/search.rs +++ b/library/alloc/src/collections/btree/search.rs @@ -128,7 +128,7 @@ impl NodeRef CursorMut<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, value: T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_after_unchecked(value, SetValZST) } } @@ -2392,7 +2392,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, value: T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_before_unchecked(value, SetValZST) } } @@ -2461,7 +2461,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_after_unchecked(&mut self, value: T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_after_unchecked(value, SetValZST) } } @@ -2480,7 +2480,7 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] pub unsafe fn insert_before_unchecked(&mut self, value: T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.inner.insert_before_unchecked(value, SetValZST) } } diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6547ed6332ea2..1f071248b15a7 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -171,8 +171,8 @@ impl LinkedList { /// This method takes ownership of the node, so the pointer should not be used again. #[inline] unsafe fn push_front_node(&mut self, node: NonNull>) { - // This method takes care not to create mutable references to whole nodes, - // to maintain validity of aliasing pointers into `element`. + // SAFETY: This method takes care not to create mutable references to + // whole nodes, to maintain validity of aliasing pointers into `element`. // SAFETY: Untriaged. unsafe { (*node.as_ptr()).next = self.head; @@ -193,9 +193,8 @@ impl LinkedList { /// Removes and returns the node at the front of the list. #[inline] fn pop_front_node(&mut self) -> Option, &A>> { - // This method takes care not to create mutable references to whole nodes, - // to maintain validity of aliasing pointers into `element`. - // SAFETY: Untriaged. + // SAFETY: This method takes care not to create mutable references to + // whole nodes, to maintain validity of aliasing pointers into `element`. self.head.map(|node| unsafe { let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.head = node.next; @@ -218,9 +217,8 @@ impl LinkedList { /// This method takes ownership of the node, so the pointer should not be used again. #[inline] unsafe fn push_back_node(&mut self, node: NonNull>) { - // This method takes care not to create mutable references to whole nodes, - // to maintain validity of aliasing pointers into `element`. - // SAFETY: Untriaged. + // SAFETY: This method takes care not to create mutable references to + // whole nodes, to maintain validity of aliasing pointers into `element`. unsafe { (*node.as_ptr()).next = None; (*node.as_ptr()).prev = self.tail; @@ -240,9 +238,8 @@ impl LinkedList { /// Removes and returns the node at the back of the list. #[inline] fn pop_back_node(&mut self) -> Option, &A>> { - // This method takes care not to create mutable references to whole nodes, - // to maintain validity of aliasing pointers into `element`. - // SAFETY: Untriaged. + // SAFETY: This method takes care not to create mutable references to + // whole nodes, to maintain validity of aliasing pointers into `element`. self.tail.map(|node| unsafe { let node = Box::from_raw_in(node.as_ptr(), &self.alloc); self.tail = node.prev; @@ -266,8 +263,8 @@ impl LinkedList { /// maintain validity of aliasing pointers. #[inline] unsafe fn unlink_node(&mut self, mut node: NonNull>) { - // SAFETY: Untriaged. - let node = unsafe { node.as_mut() }; // this one is ours now, we can create an &mut. + // SAFETY: This is ours now, we can create a &mut. + let node = unsafe { node.as_mut() }; // Not creating new mutable (unique!) references overlapping `element`. match node.prev { @@ -496,10 +493,9 @@ impl LinkedList { match self.tail { None => mem::swap(self, other), Some(mut tail) => { - // `as_mut` is okay here because we have exclusive access to the entirety - // of both lists. if let Some(mut other_head) = other.head.take() { - // SAFETY: Untriaged. + // SAFETY: `as_mut` is okay here because we have exclusive + // access to the entirety of both lists. unsafe { tail.as_mut().next = Some(other_head); other_head.as_mut().prev = Some(tail); diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 92950ebcc3dac..2b1e673be25f7 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -99,7 +99,7 @@ impl Drop for Drain<'_, T, A> { let guard = DropGuard(self); if mem::needs_drop::() && guard.0.remaining != 0 { - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = guard.0.as_slices(); @@ -117,9 +117,8 @@ impl Drop for Drain<'_, T, A> { #[inline] fn drop(&mut self) { if mem::needs_drop::() && self.0.remaining != 0 { - // SAFETY: Untriaged. + // SAFETY: We just checked that `self.remaining != 0`. unsafe { - // SAFETY: We just checked that `self.remaining != 0`. let (front, back) = self.0.as_slices(); ptr::drop_in_place(front); ptr::drop_in_place(back); @@ -270,7 +269,7 @@ impl DoubleEndedIterator for Drain<'_, T, A> { } self.remaining -= 1; let wrapped_idx = -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { self.deque.as_ref().to_wrapped_index(self.idx + self.remaining) }; // SAFETY: Untriaged. Some(unsafe { self.deque.as_mut().buffer_read(wrapped_idx) }) diff --git a/library/alloc/src/collections/vec_deque/extract_if.rs b/library/alloc/src/collections/vec_deque/extract_if.rs index 3d178d07e1055..61a75cadf4a26 100644 --- a/library/alloc/src/collections/vec_deque/extract_if.rs +++ b/library/alloc/src/collections/vec_deque/extract_if.rs @@ -74,6 +74,7 @@ where fn next(&mut self) -> Option { while self.idx < self.end { let i = self.idx; + let idx = self.vec.to_wrapped_index(i); // SAFETY: // We know that `i < self.end` from the if guard and that `self.end <= self.old_len` from // the validity of `Self`. Therefore `i` points to an element within `vec`. @@ -83,8 +84,6 @@ where // // Note: we can't use `vec.get_mut(i).unwrap()` here since the precondition for that // function is that i < vec.len, but we've set vec's length to zero. - let idx = self.vec.to_wrapped_index(i); - // SAFETY: Untriaged. let cur = unsafe { &mut *self.vec.ptr().add(idx.as_index()) }; let drained = (self.pred)(cur); // Update the index *after* the predicate is called. If the index diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs index 14ab2393ea1b5..7794fb450d776 100644 --- a/library/alloc/src/collections/vec_deque/iter.rs +++ b/library/alloc/src/collections/vec_deque/iter.rs @@ -145,9 +145,8 @@ impl<'a, T> Iterator for Iter<'a, T> { #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { - // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index // that is in bounds. - // SAFETY: Untriaged. unsafe { let i1_len = self.i1.len(); if idx < i1_len { diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index cf29810ecb7b3..9d7b99d765fac 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -209,9 +209,8 @@ impl<'a, T> Iterator for IterMut<'a, T> { #[inline] unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item { - // Safety: The TrustedRandomAccess contract requires that callers only pass an index + // SAFETY: The TrustedRandomAccess contract requires that callers only pass an index // that is in bounds. - // SAFETY: Untriaged. unsafe { let i1_len = self.i1.len(); if idx < i1_len { diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 80127ca36e1dc..40a28f9ba6c44 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -208,7 +208,7 @@ impl VecDeque { /// Moves an element out of the buffer #[inline] unsafe fn buffer_read(&mut self, off: WrappedIndex) -> T { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { ptr::read(self.ptr().add(off.as_index())) } } @@ -218,7 +218,7 @@ impl VecDeque { /// May only be called if `off < self.capacity()`. #[inline] unsafe fn buffer_write(&mut self, off: WrappedIndex, value: T) -> &mut T { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { let ptr = self.ptr().add(off.as_index()); ptr::write(ptr, value); @@ -230,7 +230,7 @@ impl VecDeque { /// `range` must lie inside `0..self.capacity()`. #[inline] unsafe fn buffer_range(&self, range: Range) -> *mut [T] { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.ptr().add(range.start).cast_slice(range.end - range.start) } } @@ -354,7 +354,7 @@ impl VecDeque { len, self.capacity() ); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { ptr::copy(self.ptr().add(src.as_index()), self.ptr().add(dst.as_index()), len); } @@ -379,7 +379,7 @@ impl VecDeque { len, self.capacity() ); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { ptr::copy_nonoverlapping( self.ptr().add(src.as_index()), @@ -589,7 +589,7 @@ impl VecDeque { /// See [`ptr::copy_nonoverlapping`]. unsafe fn copy_nonoverlapping_reversed(src: *const T, dst: *mut T, count: usize) { for i in 0..count { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { ptr::copy_nonoverlapping(src.add(count - 1 - i), dst.add(i), 1) }; } } @@ -1342,8 +1342,7 @@ impl VecDeque { // L H // [o o . o o o o o ] let len = self.head + self.len - target_cap; - // Safety: head is < target_cap, so the index is wrapped - // SAFETY: Untriaged. + // SAFETY: head is < target_cap, so the index is wrapped unsafe { self.copy_nonoverlapping( WrappedIndex::from_arbitrary_number(target_cap), @@ -1384,12 +1383,9 @@ impl VecDeque { impl Drop for Guard<'_, T, A> { #[cold] fn drop(&mut self) { - // SAFETY: Untriaged. - unsafe { - // SAFETY: This is only called if `buf.shrink_to_fit` unwinds, - // which is the only time it's safe to call `abort_shrink`. - self.deque.abort_shrink(self.old_head, self.target_cap) - } + // SAFETY: This is only called if `buf.shrink_to_fit` unwinds, + // which is the only time it's safe to call `abort_shrink`. + unsafe { self.deque.abort_shrink(self.old_head, self.target_cap) } } } @@ -1471,14 +1467,12 @@ impl VecDeque { #[doc(alias = "retain_front")] #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { - // Safe because: - // + // SAFETY: // * Any slice passed to `drop_in_place` is valid; the second case has // `len <= front.len()` and returning on `len > self.len()` ensures // `begin <= back.len()` in the first case // * The head of the VecDeque is moved before calling `drop_in_place`, // so no value is dropped twice if `drop_in_place` panics - // SAFETY: Untriaged. unsafe { if len >= self.len { return; @@ -1900,7 +1894,7 @@ impl VecDeque { // it's ok to pass them to `buffer_range` and // dereference the result. let a = unsafe { &*self.buffer_range(a_range) }; - // SAFETY: Untriaged. + // SAFETY: As above. let b = unsafe { &*self.buffer_range(b_range) }; Iter::new(a.iter(), b.iter()) } @@ -1941,7 +1935,7 @@ impl VecDeque { // it's ok to pass them to `buffer_range` and // dereference the result. let a = unsafe { &mut *self.buffer_range(a_range) }; - // SAFETY: Untriaged. + // SAFETY: As above. let b = unsafe { &mut *self.buffer_range(b_range) }; IterMut::new(a.iter_mut(), b.iter_mut()) } @@ -2672,11 +2666,10 @@ impl VecDeque { let elem = unsafe { Some(self.buffer_read(wrapped_idx)) }; let k = self.len - index - 1; - // safety: due to the nature of the if-condition, whichever wrap_copy gets called, - // its length argument will be at most `self.len / 2`, so there can't be more than - // one overlapping area. if k < index { - // SAFETY: Untriaged. + // SAFETY: due to the nature of the if-condition, whichever wrap_copy gets called, + // its length argument will be at most `self.len / 2`, so there can't be more than + // one overlapping area. unsafe { self.wrap_copy(self.wrap_add(wrapped_idx, 1), wrapped_idx, k) }; self.len -= 1; } else { @@ -3198,10 +3191,10 @@ impl VecDeque { assert!(n <= self.len()); let k = self.len - n; if n <= k { - // SAFETY: Untriaged. + // SAFETY: Ensured by check. unsafe { self.rotate_left_inner(n) } } else { - // SAFETY: Untriaged. + // SAFETY: Ensured by check. unsafe { self.rotate_right_inner(k) } } } @@ -3243,10 +3236,10 @@ impl VecDeque { assert!(n <= self.len()); let k = self.len - n; if n <= k { - // SAFETY: Untriaged. + // SAFETY: Ensured by check. unsafe { self.rotate_right_inner(n) } } else { - // SAFETY: Untriaged. + // SAFETY: Ensured by check. unsafe { self.rotate_left_inner(k) } } } @@ -3261,7 +3254,7 @@ impl VecDeque { unsafe fn rotate_left_inner(&mut self, mid: usize) { debug_assert!(mid * 2 <= self.len()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.wrap_copy(self.head, self.to_wrapped_index(self.len), mid); } @@ -3271,7 +3264,7 @@ impl VecDeque { unsafe fn rotate_right_inner(&mut self, k: usize) { debug_assert!(k * 2 <= self.len()); self.head = self.wrap_sub(self.head, k); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.wrap_copy(self.to_wrapped_index(self.len), self.head, k); } @@ -3633,7 +3626,7 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3660,7 +3653,7 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); let cap = self.capacity(); - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3712,7 +3705,7 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. @@ -3735,7 +3728,7 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index 31997f187dec2..cb3f39942339f 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -216,7 +216,7 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront> f } self.reserve(iter.remaining); - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: iter.remaining != 0. let (left, right) = iter.as_slices(); @@ -244,7 +244,7 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront SpecExtendFront(deque: &mut VecDeque, slice: &[T]) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { deque.head = deque.wrap_sub(deque.head, slice.len()); deque.copy_slice(deque.head, slice); @@ -282,7 +282,7 @@ unsafe fn prepend(deque: &mut VecDeque, slice: &[T]) { /// - `deque` must have space for `slice.len()` new elements. /// - Elements of `slice` will be copied into the deque, make sure to forget the elements if `T` is not `Copy`. unsafe fn prepend_reversed(deque: &mut VecDeque, slice: &[T]) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { deque.head = deque.wrap_sub(deque.head, slice.len()); deque.copy_slice_reversed(deque.head, slice); diff --git a/library/alloc/src/collections/vec_deque/splice.rs b/library/alloc/src/collections/vec_deque/splice.rs index bdbb61afafe94..7c8a4418d1c53 100644 --- a/library/alloc/src/collections/vec_deque/splice.rs +++ b/library/alloc/src/collections/vec_deque/splice.rs @@ -140,7 +140,7 @@ impl Drain<'_, T, A> { /// /// self.deque must be valid. unsafe fn move_tail(&mut self, additional: usize) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. let deque = unsafe { self.deque.as_mut() }; // `Drain::new` modifies the deque's len (so does `Drain::fill` here) diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 53e89235f2f5a..a079a3ef41292 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -264,7 +264,7 @@ impl CString { let bytes: Vec = self.into(); match memchr::memchr(0, &bytes) { Some(i) => Err(NulError(i, bytes)), - // SAFETY: Untriaged. + // SAFETY: We ensured there's no null bytes. None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }), } } @@ -288,7 +288,7 @@ impl CString { // This allows better optimizations if lto enabled. match memchr::memchr(0, bytes) { Some(i) => Err(NulError(i, buffer)), - // SAFETY: Untriaged. + // SAFETY: We ensured there's no null bytes. None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }), } } @@ -341,7 +341,7 @@ impl CString { #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_vec_unchecked(v: Vec) -> Self { debug_assert!(memchr::memchr(0, &v).is_none()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::_from_vec_unchecked(v) } } @@ -481,7 +481,7 @@ impl CString { pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { error: e.utf8_error(), - // SAFETY: Untriaged. + // SAFETY: Strings never contain null bytes. inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, }) } @@ -588,7 +588,7 @@ impl CString { #[stable(feature = "as_c_str", since = "1.20.0")] #[rustc_diagnostic_item = "cstring_as_c_str"] pub fn as_c_str(&self) -> &CStr { - // SAFETY: Untriaged. + // SAFETY: Ensured by `as_bytes_with_nul`. unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } @@ -604,19 +604,18 @@ impl CString { #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "into_boxed_c_str", since = "1.20.0")] pub fn into_boxed_c_str(self) -> Box { - // SAFETY: Untriaged. + // SAFETY: Typecast of [u8] to CStr is valid and we know contents have no nulls. unsafe { Box::from_raw(Box::into_raw(self.into_inner()) as *mut CStr) } } /// Bypass "move out of struct which implements [`Drop`] trait" restriction. #[inline] fn into_inner(self) -> Box<[u8]> { - // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)` + let this = mem::ManuallyDrop::new(self); + // SAFETY: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)` // so we use `ManuallyDrop` to ensure `self` is not dropped. // Then we can return the box directly without invalidating it. // See https://github.com/rust-lang/rust/issues/62553. - let this = mem::ManuallyDrop::new(self); - // SAFETY: Untriaged. unsafe { ptr::read(&this.inner) } } @@ -641,7 +640,7 @@ impl CString { #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::_from_vec_with_nul_unchecked(v) } } @@ -710,7 +709,7 @@ impl CString { impl Drop for CString { #[inline] fn drop(&mut self) { - // SAFETY: Untriaged. + // SAFETY: Length is always at least one. unsafe { *self.inner.get_unchecked_mut(0) = 0; } @@ -811,7 +810,7 @@ impl From> for CString { #[inline] fn from(s: Box) -> CString { let raw = Box::into_raw(s) as *mut [u8]; - // SAFETY: Untriaged. + // SAFETY: Converting a *mut CStr -> *mut [u8] -> CString is valid. CString { inner: unsafe { Box::from_raw(raw) } } } } @@ -822,7 +821,7 @@ impl From>> for CString { /// copying nor checking for inner nul bytes. #[inline] fn from(v: Vec>) -> CString { - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // Transmute `Vec>` to `Vec`. let v: Vec = { @@ -917,7 +916,7 @@ impl From for Arc { #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); - // SAFETY: Untriaged. + // SAFETY: Type conversion is valid. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } } } @@ -930,7 +929,7 @@ impl From<&CStr> for Arc { #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); - // SAFETY: Untriaged. + // SAFETY: Type conversion is valid. unsafe { Arc::from_raw(Arc::into_raw(arc) as *const CStr) } } } @@ -953,7 +952,7 @@ impl From for Rc { #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); - // SAFETY: Untriaged. + // SAFETY: Type conversion is valid. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } } } @@ -965,7 +964,7 @@ impl From<&CStr> for Rc { #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); - // SAFETY: Untriaged. + // SAFETY: Type conversion is valid. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const CStr) } } } diff --git a/library/alloc/src/io/cursor.rs b/library/alloc/src/io/cursor.rs index df01104b1f733..ef213a0069f3f 100644 --- a/library/alloc/src/io/cursor.rs +++ b/library/alloc/src/io/cursor.rs @@ -155,9 +155,8 @@ fn reserve_and_pad( // to eliminate that extra branch let spare = vec.spare_capacity_mut(); debug_assert!(spare.len() >= diff); - // Safety: we have allocated enough capacity for this. + // SAFETY: we have allocated enough capacity for this. // And we are only writing, not reading - // SAFETY: Untriaged. unsafe { spare.get_unchecked_mut(..diff).fill(core::mem::MaybeUninit::new(0)); vec.set_len(pos); @@ -177,7 +176,7 @@ where A: Allocator, { debug_assert!(vec.capacity() >= pos + buf.len()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { vec.as_mut_ptr().add(pos).copy_from(buf.as_ptr(), buf.len()) }; pos + buf.len() } @@ -201,9 +200,8 @@ where let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?; // Write the buf then progress the vec forward if necessary - // Safety: we have ensured that the capacity is available + // SAFETY: we have ensured that the capacity is available // and that all bytes get written up to pos - // SAFETY: Untriaged. unsafe { pos = vec_write_all_unchecked(pos, vec, buf); if pos > vec.len() { diff --git a/library/alloc/src/io/error.rs b/library/alloc/src/io/error.rs index 7813b26bc460b..020029b93cd36 100644 --- a/library/alloc/src/io/error.rs +++ b/library/alloc/src/io/error.rs @@ -215,8 +215,7 @@ impl Error { { Ok(*err) } else { - // Safety: We have just checked that the condition is true - // SAFETY: Untriaged. + // SAFETY: We have just checked that the condition is true unsafe { core::hint::unreachable_unchecked() } } } else { @@ -255,9 +254,7 @@ fn custom_owner_from_box( /// /// `ptr` must be valid to pass into `Box::from_raw`. unsafe fn drop_box_raw(ptr: *mut T) { - // SAFETY - // Caller ensures `ptr` is valid to pass into `Box::from_raw`. - // SAFETY: Untriaged. + // SAFETY: Caller ensures `ptr` is valid to pass into `Box::from_raw`. drop(unsafe { Box::from_raw(ptr) }) } diff --git a/library/alloc/src/io/read.rs b/library/alloc/src/io/read.rs index 4a9e15e5c4094..d1266d658d369 100644 --- a/library/alloc/src/io/read.rs +++ b/library/alloc/src/io/read.rs @@ -632,7 +632,7 @@ pub trait Read { self.read_buf_exact(borrowed_buf.unfilled())?; // Guard against incorrect `read_buf_exact` implementations. assert_eq!(borrowed_buf.len(), N); - // SAFETY: Untriaged. + // SAFETY: Buffer was initialised above. Ok(unsafe { MaybeUninit::array_assume_init(buf) }) } diff --git a/library/alloc/src/io/util.rs b/library/alloc/src/io/util.rs index 0fd55a7eaab87..b4cc4046bae4b 100644 --- a/library/alloc/src/io/util.rs +++ b/library/alloc/src/io/util.rs @@ -287,9 +287,8 @@ impl Read for Take { unsafe { buf.set_init() }; } - // SAFETY: Untriaged. + // SAFETY: filled bytes have been filled unsafe { - // SAFETY: filled bytes have been filled buf.advance(filled); } diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index d0fa74f7f9ee0..a65f6ca9059e4 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -38,14 +38,14 @@ enum AllocInit { type Cap = core::num::niche_types::UsizeNoHighBit; -// SAFETY: Untriaged. +// SAFETY: 0 *definitely* is less than isize::MAX. const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) }; /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. /// /// # Safety: cap must be <= `isize::MAX`. const unsafe fn new_cap(cap: usize) -> Cap { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } } } @@ -416,7 +416,7 @@ impl RawVec { /// Panics if the given amount is *larger* than the current capacity. #[inline] pub(crate) fn try_shrink_to_fit(&mut self, cap: usize) -> Result<(), TryReserveError> { - // SAFETY: Untriaged. + // SAFETY: Layout is valid for T. unsafe { self.inner.try_shrink_to_fit(cap, T::LAYOUT) } } } @@ -438,7 +438,7 @@ const impl RawVecInner { fn with_capacity_in(capacity: usize, alloc: A, elem_layout: Layout) -> Self { match Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc, elem_layout) { Ok(this) => { -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { // Make it more obvious that a subsequent Vec::reserve(capacity) will not allocate. hint::assert_unchecked(!this.needs_to_grow(0, capacity, elem_layout)); @@ -482,7 +482,7 @@ const impl RawVecInner { // here should change to `ptr.len() / size_of::()`. Ok(Self { ptr: Unique::from(ptr.cast()), -// SAFETY: Untriaged. + // SAFETY: Untriaged. cap: unsafe { Cap::new_unchecked(capacity) }, alloc, }) @@ -554,11 +554,11 @@ const impl RawVecInner { ) -> Result, TryReserveError> { let new_layout = layout_array(cap, elem_layout)?; -// SAFETY: Untriaged. + // SAFETY: Untriaged. let memory = if let Some((ptr, old_layout)) = unsafe { self.current_memory(elem_layout) } { // FIXME(const-hack): switch to `debug_assert_eq` debug_assert!(old_layout.align() == new_layout.align()); -// SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { // The allocator checks for alignment equality hint::assert_unchecked(old_layout.align() == new_layout.align()); @@ -600,7 +600,7 @@ impl RawVecInner { #[inline] const unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } } @@ -753,7 +753,7 @@ impl RawVecInner { #[cfg(not(no_global_oom_handling))] #[inline] unsafe fn shrink_to_fit(&mut self, cap: usize, elem_layout: Layout) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. if let Err(err) = unsafe { self.shrink(cap, elem_layout) } { handle_error(err); } @@ -770,7 +770,7 @@ impl RawVecInner { cap: usize, elem_layout: Layout, ) -> Result<(), TryReserveError> { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { self.shrink(cap, elem_layout) } } @@ -786,7 +786,7 @@ impl RawVecInner { // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / size_of::()`. self.ptr = Unique::from(ptr.cast()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. self.cap = unsafe { Cap::new_unchecked(cap) }; } @@ -856,7 +856,7 @@ impl RawVecInner { // SAFETY: Untriaged. unsafe { self.alloc.deallocate(ptr, layout) }; self.ptr = -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; self.cap = ZERO_CAP; } else { @@ -889,9 +889,9 @@ const impl RawVecInner { /// Ideally this function would take `self` by move, but it cannot because it exists to be /// called from a `Drop` impl. unsafe fn deallocate(&mut self, elem_layout: Layout) { - // SAFETY: Precondition passed to caller + // SAFETY: Untriaged. if let Some((ptr, layout)) = unsafe { self.current_memory(elem_layout) } { - // SAFETY: Untriaged. + // SAFETY: Precondition passed to caller unsafe { self.alloc.deallocate(ptr, layout); } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 7a55dea57af9d..64f6c40c007dd 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -359,13 +359,13 @@ unsafe impl CloneFromCell for Rc {} impl Rc { #[inline] unsafe fn from_inner(ptr: NonNull>) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_inner_in(ptr, Global) } } #[inline] unsafe fn from_ptr(ptr: *mut RcInner) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) } } } @@ -373,16 +373,15 @@ impl Rc { impl Rc { #[inline(always)] fn inner(&self) -> &RcInner { - // This unsafety is ok because while this Rc is alive we're guaranteed + // SAFETY: While this Rc is alive we're guaranteed // that the inner pointer is valid. - // SAFETY: Untriaged. unsafe { self.ptr.as_ref() } } #[inline] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pulling out the allocator we already own. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -393,7 +392,7 @@ impl Rc { #[inline] unsafe fn from_ptr_in(ptr: *mut RcInner, alloc: A) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } } @@ -407,7 +406,7 @@ impl Rc { // Destroy the contained object. // We cannot use `get_mut_unchecked` here, because `self.alloc` is borrowed. - // SAFETY: Untriaged. + // SAFETY: `self.ptr` is *not* borrowed. unsafe { ptr::drop_in_place(&mut (*self.ptr.as_ptr()).value); } @@ -427,11 +426,10 @@ impl Rc { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(value: T) -> Rc { - // There is an implicit weak pointer owned by all the strong + // SAFETY: There is an implicit weak pointer owned by all the strong // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. - // SAFETY: Untriaged. unsafe { Self::from_inner( Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value })) @@ -575,11 +573,10 @@ impl Rc { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub fn try_new(value: T) -> Result, AllocError> { - // There is an implicit weak pointer owned by all the strong + // SAFETY: There is an implicit weak pointer owned by all the strong // pointers, which ensures that the weak destructor never frees // the allocation while the strong destructor is running, even // if the weak pointer is stored inside the strong one. - // SAFETY: Untriaged. unsafe { Ok(Self::from_inner( Box::leak(Box::try_new(RcInner { @@ -661,7 +658,7 @@ impl Rc { #[stable(feature = "pin", since = "1.33.0")] #[must_use] pub fn pin(value: T) -> Pin> { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Rc::new(value)) } } @@ -1051,7 +1048,7 @@ impl Rc { where A: 'static, { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Rc::new_in(value, alloc)) } } @@ -1679,8 +1676,7 @@ impl Rc { pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); - // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped - // SAFETY: Untriaged. + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped let alloc = unsafe { ptr::read(&this.alloc) }; (ptr, alloc) } @@ -1938,7 +1934,7 @@ impl Rc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { drop(Rc::from_raw_in(ptr, alloc)) }; } @@ -1976,7 +1972,7 @@ impl Rc { #[inline] #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { - // SAFETY: Untriaged. + // SAFETY: Ensured by uniqueness check. if Rc::is_unique(this) { unsafe { Some(Rc::get_mut_unchecked(this)) } } else { None } } @@ -2163,12 +2159,11 @@ impl Rc { ptr::write(this, in_progress.into_rc()); } } - // This unsafety is ok because we're guaranteed that the pointer + // SAFETY: We're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the `Rc` itself to be `mut`, so we're returning the only possible // reference to the allocation. - // SAFETY: Untriaged. unsafe { &mut this.ptr.as_mut().value } } } @@ -2232,7 +2227,7 @@ impl Rc { #[stable(feature = "rc_downcast", since = "1.29.0")] pub fn downcast(self) -> Result, Self> { if (*self).is::() { - // SAFETY: Untriaged. + // SAFETY: Check ensures typecast is corrext. unsafe { let (ptr, alloc) = Rc::into_inner_with_allocator(self); Ok(Rc::from_inner_in(ptr.cast(), alloc)) @@ -2271,7 +2266,7 @@ impl Rc { #[inline] #[unstable(feature = "downcast_unchecked", issue = "90850")] pub unsafe fn downcast_unchecked(self) -> Rc { - // SAFETY: Untriaged. + // SAFETY: Check ensures typecast is correct. unsafe { let (ptr, alloc) = Rc::into_inner_with_allocator(self); Rc::from_inner_in(ptr.cast(), alloc) @@ -2632,8 +2627,7 @@ impl Default for Rc { #[inline] fn default() -> Self { let rc = Rc::<[u8]>::default(); - // `[u8]` has the same layout as `str`. - // SAFETY: Untriaged. + // SAFETY: `[u8]` has the same layout as `str`. unsafe { Rc::from_raw(Rc::into_raw(rc) as *const str) } } } @@ -2660,7 +2654,7 @@ where { #[inline] fn default() -> Self { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Rc::::default()) } } } @@ -3228,11 +3222,8 @@ impl> ToRcSlice for I { (low, high) ); - // SAFETY: Untriaged. - unsafe { - // SAFETY: We need to ensure that the iterator has an exact length and we have. - Rc::from_iter_exact(self, low) - } + // SAFETY: We need to ensure that the iterator has an exact length and we have. + unsafe { Rc::from_iter_exact(self, low) } } else { // TrustedLen contract guarantees that `upper_bound == None` implies an iterator // length exceeding `usize::MAX`. @@ -3397,7 +3388,7 @@ impl Weak { #[inline] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_raw_in(ptr, Global) } } @@ -3520,8 +3511,7 @@ impl Weak { pub fn into_raw_with_allocator(self) -> (*const T, A) { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); - // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped - // SAFETY: Untriaged. + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped let alloc = unsafe { ptr::read(&this.alloc) }; (result, alloc) } @@ -4380,7 +4370,7 @@ impl UniqueRc { #[cfg(not(no_global_oom_handling))] fn unwrap(this: Self) -> T { let this = ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads. let val: T = unsafe { ptr::read(&**this) }; let _weak = Weak { ptr: this.ptr, alloc: Global }; @@ -4392,15 +4382,15 @@ impl UniqueRc { impl UniqueRc { #[cfg(not(no_global_oom_handling))] unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Caller upholds that data behind pointer is initialised & correct. let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original RcInner. - // SAFETY: Untriaged. + // SAFETY: As above. let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner }; Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, _marker: PhantomData, _marker2: PhantomData, @@ -4489,7 +4479,7 @@ impl UniqueRc { #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -4520,7 +4510,7 @@ impl UniqueRc { impl UniqueRc, A> { unsafe fn assume_init(self) -> UniqueRc { let (ptr, alloc) = UniqueRc::into_inner_with_allocator(self); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { UniqueRc::from_inner_in(ptr.cast(), alloc) } } } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index d729eb7e92199..a2326ae33d5a7 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -446,11 +446,10 @@ impl [T] { fn to_vec(s: &[Self], alloc: A) -> Vec { let len = s.len(); let mut v = Vec::with_capacity_in(len, alloc); - // SAFETY: - // allocated above with the capacity of `s`, and initialize to `s.len()` in - // ptr::copy_to_non_overlapping below. if len > 0 { - // SAFETY: Untriaged. + // SAFETY: + // allocated above with the capacity of `s`, and initialize to `s.len()` in + // ptr::copy_to_non_overlapping below. unsafe { s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), len); v.set_len(len); diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index b9e79160f8d8d..b1cccf7c234c8 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -913,7 +913,7 @@ impl str { #[must_use] #[inline] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Box::from_raw(Box::into_raw(v) as *mut str) } } @@ -994,7 +994,7 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; } - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: ascii_prefix_len bytes have been initialized above out.set_len(ascii_prefix_len); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 19f06cbedac34..e95be5a97a657 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -985,7 +985,7 @@ impl String { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { String { vec: Vec::from_raw_parts(buf, length, capacity) } } } @@ -3468,8 +3468,7 @@ impl IntoChars { #[unstable(feature = "string_into_chars", issue = "133125")] #[inline] pub fn into_string(self) -> String { - // Safety: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. - // SAFETY: Untriaged. + // SAFETY: `bytes` are kept in UTF-8 form, only removing whole `char`s at a time. unsafe { String::from_utf8_unchecked(self.bytes.collect()) } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 9e780b795317c..fd34974081a5a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -300,12 +300,12 @@ unsafe impl CloneFromCell for Arc {} impl Arc { unsafe fn from_inner(ptr: NonNull>) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_inner_in(ptr, Global) } } unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_ptr_in(ptr, Global) } } } @@ -314,7 +314,7 @@ impl Arc { #[inline] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -325,7 +325,7 @@ impl Arc { #[inline] unsafe fn from_ptr_in(ptr: *mut ArcInner, alloc: A) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) } } } @@ -446,7 +446,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, }); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid. unsafe { Self::from_inner(Box::leak(x).into()) } } @@ -581,7 +581,7 @@ impl Arc { #[stable(feature = "pin", since = "1.33.0")] #[must_use] pub fn pin(data: T) -> Pin> { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Arc::new(data)) } } @@ -589,7 +589,7 @@ impl Arc { #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn try_pin(data: T) -> Result>, AllocError> { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Ok(Pin::new_unchecked(Arc::try_new(data)?)) } } @@ -614,7 +614,7 @@ impl Arc { weak: atomic::AtomicUsize::new(1), data, })?; - // SAFETY: Untriaged. + // SAFETY: Pointer is valid. unsafe { Ok(Self::from_inner(Box::leak(x).into())) } } @@ -801,7 +801,7 @@ impl Arc { alloc, ); let (ptr, alloc) = Box::into_unique(x); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid. unsafe { Self::from_inner_in(ptr.into(), alloc) } } @@ -928,7 +928,7 @@ impl Arc { }, alloc, )); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid since we constructed it. let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into(); let init_ptr: NonNull> = uninit_ptr.cast(); @@ -983,7 +983,7 @@ impl Arc { where A: 'static, { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } } @@ -995,7 +995,7 @@ impl Arc { where A: 'static, { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } } @@ -1026,7 +1026,7 @@ impl Arc { alloc, )?; let (ptr, alloc) = Box::into_unique(x); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid since we created it. Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) }) } @@ -1151,9 +1151,9 @@ impl Arc { acquire!(this.inner().strong); let this = ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads. let elem: T = unsafe { ptr::read(&this.ptr.as_ref().data) }; - // SAFETY: Untriaged. + // SAFETY: As above. let alloc: A = unsafe { ptr::read(&this.alloc) }; // copy the allocator // Make a weak pointer to clean up the implicit strong-weak reference @@ -1278,9 +1278,8 @@ impl Arc { // in `drop_slow`. Instead of dropping the value behind the pointer, // it is read and eventually returned; `ptr::read` has the same // safety conditions as `ptr::drop_in_place`. - let inner = unsafe { ptr::read(Self::get_mut_unchecked(&mut this)) }; - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads. let alloc = unsafe { ptr::read(&this.alloc) }; drop(Weak { ptr: this.ptr, alloc }); @@ -1629,7 +1628,7 @@ impl Arc<[mem::MaybeUninit], A> { #[inline] pub unsafe fn assume_init(self) -> Arc<[T], A> { let (ptr, alloc) = Arc::into_inner_with_allocator(self); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Arc::from_ptr_in(ptr.as_ptr() as _, alloc) } } } @@ -1702,7 +1701,7 @@ impl Arc { #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Arc::from_raw_in(ptr, Global) } } @@ -1765,7 +1764,7 @@ impl Arc { #[inline] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] pub unsafe fn increment_strong_count(ptr: *const T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Arc::increment_strong_count_in(ptr, Global) } } @@ -1806,7 +1805,7 @@ impl Arc { #[inline] #[stable(feature = "arc_mutate_strong_count", since = "1.51.0")] pub unsafe fn decrement_strong_count(ptr: *const T) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Arc::decrement_strong_count_in(ptr, Global) } } } @@ -1846,8 +1845,7 @@ impl Arc { pub fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = mem::ManuallyDrop::new(this); let ptr = Self::as_ptr(&this); - // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped - // SAFETY: Untriaged. + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped let alloc = unsafe { ptr::read(&this.alloc) }; (ptr, alloc) } @@ -1953,7 +1951,7 @@ impl Arc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { let offset = data_offset(ptr); @@ -2115,7 +2113,7 @@ impl Arc { A: Clone, { // Retain Arc, but don't touch refcount by wrapping in ManuallyDrop - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. let arc = unsafe { mem::ManuallyDrop::new(Arc::from_raw_in(ptr, alloc)) }; // Now increase refcount, but don't drop new refcount either let _arc_clone: mem::ManuallyDrop<_> = arc.clone(); @@ -2161,18 +2159,17 @@ impl Arc { #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn decrement_strong_count_in(ptr: *const T, alloc: A) { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { drop(Arc::from_raw_in(ptr, alloc)) }; } #[inline] fn inner(&self) -> &ArcInner { - // This unsafety is ok because while this arc is alive we're guaranteed + // SAFETY: While this arc is alive we're guaranteed // that the inner pointer is valid. Furthermore, we know that the // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. - // SAFETY: Untriaged. unsafe { self.ptr.as_ref() } } @@ -2265,7 +2262,7 @@ impl Arc { mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> *mut ArcInner { let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr()); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. debug_assert_eq!(unsafe { Layout::for_value_raw(inner) }, layout); // SAFETY: Untriaged. @@ -2491,7 +2488,7 @@ impl Clone for Arc { abort(); } - // SAFETY: Untriaged. + // SAFETY: Pointer is valid & allocator corresponds to the one used to allocate it. unsafe { Self::from_inner_in(self.ptr, self.alloc.clone()) } } } @@ -2659,9 +2656,8 @@ impl Arc { this.inner().strong.store(1, Release); } - // As with `get_mut()`, the unsafety is ok because our reference was + // SAFETY: As with `get_mut()`, our reference was // either unique to begin with, or became one upon cloning the contents. - // SAFETY: Untriaged. unsafe { Self::get_mut_unchecked(this) } } } @@ -2731,12 +2727,11 @@ impl Arc { #[stable(feature = "arc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Self::is_unique(this) { - // This unsafety is ok because we're guaranteed that the pointer + // SAFETY: We're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. - // SAFETY: Untriaged. unsafe { Some(Arc::get_mut_unchecked(this)) } } else { None @@ -3001,7 +2996,7 @@ impl Arc { T: Any + Send + Sync, { if (*self).is::() { - // SAFETY: Untriaged. + // SAFETY: Check ensures the typecast is okay. unsafe { let (ptr, alloc) = Arc::into_inner_with_allocator(self); Ok(Arc::from_inner_in(ptr.cast(), alloc)) @@ -3043,7 +3038,7 @@ impl Arc { where T: Any + Send + Sync, { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { let (ptr, alloc) = Arc::into_inner_with_allocator(self); Arc::from_inner_in(ptr.cast(), alloc) @@ -3151,7 +3146,7 @@ impl Weak { #[inline] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Weak::from_raw_in(ptr, Global) } } @@ -3273,8 +3268,7 @@ impl Weak { pub fn into_raw_with_allocator(self) -> (*const T, A) { let this = mem::ManuallyDrop::new(self); let result = this.as_ptr(); - // Safety: `this` is ManuallyDrop so the allocator will not be double-dropped - // SAFETY: Untriaged. + // SAFETY: `this` is ManuallyDrop so the allocator will not be double-dropped let alloc = unsafe { ptr::read(&this.alloc) }; (result, alloc) } @@ -3926,7 +3920,7 @@ impl Default for Arc { NonNull::new(inner.as_ptr() as *mut ArcInner).unwrap(); // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. let this: mem::ManuallyDrop> = -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; (*this).clone() } @@ -3949,7 +3943,7 @@ impl Default for Arc<[T]> { let inner: NonNull> = inner.cast(); // `this` semantically is the Arc "owned" by the static, so make sure not to drop it. let this: mem::ManuallyDrop> = -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { mem::ManuallyDrop::new(Arc::from_inner(inner)) }; return (*this).clone(); } @@ -3969,7 +3963,7 @@ where { #[inline] fn default() -> Self { - // SAFETY: Untriaged. + // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Arc::::default()) } } } @@ -4305,11 +4299,8 @@ impl> ToArcSlice for I { (low, high) ); - // SAFETY: Untriaged. - unsafe { - // SAFETY: We need to ensure that the iterator has an exact length and we have. - Arc::from_iter_exact(self, low) - } + // SAFETY: We need to ensure that the iterator has an exact length and we have. + unsafe { Arc::from_iter_exact(self, low) } } else { // TrustedLen contract guarantees that `upper_bound == None` implies an iterator // length exceeding `usize::MAX`. @@ -4842,7 +4833,7 @@ impl UniqueArc { #[cfg(not(no_global_oom_handling))] fn unwrap(this: Self) -> T { let this = ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads and `this` is ManuallyDrop. let val: T = unsafe { ptr::read(&**this) }; let _weak = Weak { ptr: this.ptr, alloc: Global }; @@ -4854,15 +4845,15 @@ impl UniqueArc { impl UniqueArc { #[cfg(not(no_global_oom_handling))] unsafe fn from_raw(ptr: *const T) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. let offset = unsafe { data_offset(ptr) }; // Reverse the offset to find the original ArcInner. - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut ArcInner }; Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. ptr: unsafe { NonNull::new_unchecked(rc_ptr) }, _marker: PhantomData, _marker2: PhantomData, @@ -4954,7 +4945,7 @@ impl UniqueArc { #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); - // SAFETY: Untriaged. + // SAFETY: Pointer is valid for reads and won't be double-dropped. (this.ptr, unsafe { ptr::read(&this.alloc) }) } @@ -4997,7 +4988,7 @@ impl UniqueArc { impl UniqueArc, A> { unsafe fn assume_init(self) -> UniqueArc { let (ptr, alloc) = UniqueArc::into_inner_with_allocator(self); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { UniqueArc::from_inner_in(ptr.cast(), alloc) } } } diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index bef7c86cc102d..7ec17d4a384a7 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -62,7 +62,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { #[must_use] #[inline] pub fn allocator(&self) -> &A { - // SAFETY: Untriaged. + // SAFETY: `vec` is valid for reads. unsafe { self.vec.as_ref().allocator() } } diff --git a/library/alloc/src/vec/extract_if.rs b/library/alloc/src/vec/extract_if.rs index a457bf7c4ffcc..366ee1c4e0cbf 100644 --- a/library/alloc/src/vec/extract_if.rs +++ b/library/alloc/src/vec/extract_if.rs @@ -43,7 +43,7 @@ impl<'a, T, F, A: Allocator> ExtractIf<'a, T, F, A> { let Range { start, end } = slice::range(range, ..old_len); // Guard against the vec getting leaked (leak amplification) - // SAFETY: Untriaged. + // SAFETY: Setting length to 0 is always okay. unsafe { vec.set_len(0); } @@ -138,14 +138,13 @@ where // SAFETY: we always keep first `self.idx - self.del` elements valid. let retained = unsafe { slice::from_raw_parts(start, self.idx - self.del) }; - // SAFETY: we have not yet touched elements starting at `self.idx`. let valid_tail = -// SAFETY: Untriaged. + // SAFETY: we have not yet touched elements starting at `self.idx`. unsafe { slice::from_raw_parts(start.add(self.idx), self.old_len - self.idx) }; - // SAFETY: `end - idx <= old_len - idx`, because `end <= old_len`. Also `idx <= end` by invariant. let (remainder, skipped_tail) = -// SAFETY: Untriaged. + // SAFETY: `end - idx <= old_len - idx`, because `end <= old_len`. + // Also `idx <= end` by invariant. unsafe { valid_tail.split_at_unchecked(self.end - self.idx) }; f.debug_struct("ExtractIf") diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index 6417a176fd613..2cc00e1d11139 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -395,10 +395,9 @@ where let len = self.size(); let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf }; for i in 0..len { - // Safety: InplaceIterable contract guarantees that for every element we read + // SAFETY: InplaceIterable contract guarantees that for every element we read // one slot in the underlying storage will have been freed up and we can immediately // write back the result. - // SAFETY: Untriaged. unsafe { let dst = dst_buf.add(i); debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation"); diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index bf4e32285d164..c71ef6dddc620 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -21,12 +21,12 @@ use crate::raw_vec::RawVec; macro non_null { (mut $place:expr, $t:ident) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { &mut *((&raw mut $place) as *mut NonNull<$t>) } }}, ($place:expr, $t:ident) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { *((&raw const $place) as *const NonNull<$t>) } }}, } @@ -201,7 +201,7 @@ impl IntoIter { /// memory if there are any remaining elements. #[inline] unsafe fn dealloc_only(&mut self) { - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { // SAFETY: our caller promises not to touch `*self` again let alloc = ManuallyDrop::take(&mut self.alloc); @@ -325,21 +325,18 @@ impl Iterator for IntoIter { if T::IS_ZST { if len < N { self.forget_remaining_elements(); - // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct - // SAFETY: Untriaged. + // SAFETY: ZSTs can be conjured ex nihilo, only the amount has to be correct return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, 0..len) }); } self.end = self.end.wrapping_byte_sub(N); - // Safety: ditto - // SAFETY: Untriaged. + // SAFETY: ditto return Ok(unsafe { raw_ary.transpose().assume_init() }); } if len < N { - // Safety: `len` indicates that this many elements are available and we just checked that - // it fits into the array. - // SAFETY: Untriaged. + // SAFETY: `len` indicates that this many elements are available and we + // just checked that it fits into the array. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); self.forget_remaining_elements(); @@ -347,9 +344,8 @@ impl Iterator for IntoIter { } } - // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. - // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, N); self.ptr = self.ptr.add(N); @@ -469,21 +465,18 @@ impl DoubleEndedIterator for IntoIter { if T::IS_ZST { if len < N { self.forget_remaining_elements(); - // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct - // SAFETY: Untriaged. + // SAFETY: ZSTs can be conjured ex nihilo, only the amount has to be correct return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, N - len..N) }); } self.end = self.end.wrapping_byte_sub(N); - // Safety: ditto - // SAFETY: Untriaged. + // SAFETY: ditto return Ok(unsafe { MaybeUninit::array_assume_init(raw_ary) }); } if len < N { - // Safety: `len` indicates that this many elements are available and we just checked that - // it fits into the array. - // SAFETY: Untriaged. + // SAFETY: `len` indicates that this many elements are available + // and we just checked that it fits into the array. unsafe { ptr::copy_nonoverlapping(self.ptr.as_ptr(), raw_ary.as_mut_ptr() as *mut T, len); self.forget_remaining_elements(); @@ -491,9 +484,8 @@ impl DoubleEndedIterator for IntoIter { } } - // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize + // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize // the array. - // SAFETY: Untriaged. unsafe { ptr::copy_nonoverlapping( self.ptr.add(len - N).as_ptr(), diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index a9167b726e88c..bd016ef3ba283 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -153,7 +153,7 @@ macro_rules! impl_is_zero_option_of_int { #[inline] fn is_zero(&self) -> bool { const { -// SAFETY: Untriaged. + // SAFETY: All-zeroes is a valid bitpattern for these primitives. let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() }; assert!(none.is_none()); } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 78c70b0942fb2..c52701e0a712e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -640,7 +640,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } } @@ -740,7 +740,7 @@ impl Vec { #[stable(feature = "box_vec_non_null", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_parts(ptr: NonNull, length: usize, capacity: usize) -> Self { - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Self::from_parts_in(ptr, length, capacity, Global) } } @@ -1037,7 +1037,7 @@ const impl Vec { if len == self.buf.capacity() { self.buf.grow_one(); } -// SAFETY: Untriaged. + // SAFETY: Untriaged. unsafe { let end = self.as_mut_ptr().add(len); ptr::write(end, value); @@ -1199,7 +1199,7 @@ impl Vec { "Vec::from_raw_parts_in requires that length <= capacity", (length: usize = length, capacity: usize = capacity) => length <= capacity ); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } } @@ -1315,7 +1315,7 @@ impl Vec { "Vec::from_parts_in requires that length <= capacity", (length: usize = length, capacity: usize = capacity) => length <= capacity ); - // SAFETY: Untriaged. + // SAFETY: Upheld by caller. unsafe { Vec { buf: RawVec::from_nonnull_in(ptr, capacity, alloc), len: length } } } @@ -2732,10 +2732,9 @@ impl Vec { fn drop(&mut self) { /* This code gets executed when `same_bucket` panics */ - /* SAFETY: invariant guarantees that `read - write` - * and `len - read` never overflow and that the copy is always - * in-bounds. */ - // SAFETY: Untriaged. + // SAFETY: invariant guarantees that `read - write` + // and `len - read` never overflow and that the copy is always + // in-bounds. unsafe { let ptr = self.vec.as_mut_ptr(); let len = self.vec.len(); @@ -2768,16 +2767,14 @@ impl Vec { // Construct gap first and then drop item to avoid memory corruption if `T::drop` panics. let mut gap = FillGapOnDrop { read: first_duplicate_idx + 1, write: first_duplicate_idx, vec: self }; - // SAFETY: Untriaged. + // SAFETY: we checked that first_duplicate_idx in bounds before. + // If drop panics, `gap` would remove this item without drop. unsafe { - // SAFETY: we checked that first_duplicate_idx in bounds before. - // If drop panics, `gap` would remove this item without drop. ptr::drop_in_place(start.add(first_duplicate_idx)); } - /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr - * are always in-bounds and read_ptr never aliases prev_ptr */ - // SAFETY: Untriaged. + // SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr + // are always in-bounds and read_ptr never aliases prev_ptr unsafe { while gap.read < len { let read_ptr = start.add(gap.read); @@ -2854,7 +2851,7 @@ impl Vec { return Err(value); } - // SAFETY: Untriaged. + // SAFETY: See within. unsafe { let end = self.as_mut_ptr().add(self.len); ptr::write(end, value); diff --git a/library/alloc/src/vec/spec_from_iter_nested.rs b/library/alloc/src/vec/spec_from_iter_nested.rs index 5a078f36aeb8c..b211687f20730 100644 --- a/library/alloc/src/vec/spec_from_iter_nested.rs +++ b/library/alloc/src/vec/spec_from_iter_nested.rs @@ -28,9 +28,8 @@ where let initial_capacity = cmp::max(RawVec::::MIN_NON_ZERO_CAP, lower.saturating_add(1)); let mut vector = Vec::with_capacity(initial_capacity); - // SAFETY: Untriaged. + // SAFETY: We requested capacity at least 1 unsafe { - // SAFETY: We requested capacity at least 1 ptr::write(vector.as_mut_ptr(), element); vector.set_len(1); } diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs index 33b08be9423be..b7c921865f1f5 100644 --- a/library/alloc/src/vec/splice.rs +++ b/library/alloc/src/vec/splice.rs @@ -105,7 +105,7 @@ impl Drain<'_, T, A> { /// Fill that range as much as possible with new elements from the `replace_with` iterator. /// Returns `true` if we filled the entire range. (`replace_with.next()` didn’t return `None`.) unsafe fn fill>(&mut self, replace_with: &mut I) -> bool { - // SAFETY: Untriaged. + // SAFETY: Pointer is valid. let vec = unsafe { self.vec.as_mut() }; let range_start = vec.len; let range_end = self.tail_start; @@ -124,7 +124,7 @@ impl Drain<'_, T, A> { /// Makes room for inserting more elements before the tail. unsafe fn move_tail(&mut self, additional: usize) { - // SAFETY: Untriaged. + // SAFETY: Pointer is valid. let vec = unsafe { self.vec.as_mut() }; let len = self.tail_start + self.tail_len; vec.buf.reserve(len, additional); diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs index 481d648435127..4df66841762f1 100644 --- a/library/alloc/src/wtf8/mod.rs +++ b/library/alloc/src/wtf8/mod.rs @@ -147,14 +147,13 @@ impl Wtf8Buf { Ok(ch) => string.push_char(ch), Err(surrogate) => { let surrogate = surrogate.unpaired_surrogate(); - // Surrogates are known to be in the code point range. - // SAFETY: Untriaged. + // SAFETY: Surrogates are known to be in the code point range. let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) }; // The string will now contain an unpaired surrogate. string.is_known_utf8 = false; // Skip the WTF-8 concatenation check, // surrogate pairs are already decoded by decode_utf16 - // SAFETY: Untriaged. + // SAFETY: As above. unsafe { string.push_code_point_unchecked(code_point); } @@ -181,10 +180,9 @@ impl Wtf8Buf { #[inline] pub fn as_mut_slice(&mut self) -> &mut Wtf8 { - // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would + // SAFETY: `Wtf8` doesn't expose any way to mutate the bytes that would // cause them to change from well-formed UTF-8 to ill-formed UTF-8, // which would break the assumptions of the `is_known_utf8` field. - // SAFETY: Untriaged. unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) } } @@ -377,7 +375,7 @@ impl Wtf8Buf { /// the original WTF-8 string is returned instead. pub fn into_string(self) -> Result { if self.is_known_utf8 || self.next_surrogate(0).is_none() { - // SAFETY: Untriaged. + // SAFETY: Check ensures we're UTF-8. Ok(unsafe { String::from_utf8_unchecked(self.bytes) }) } else { Err(self) From 21f070f570e3196f3c5dfca633a02f45dd6596f2 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Thu, 13 Aug 2026 00:28:41 +0200 Subject: [PATCH 5/8] changes: see within --- library/alloc/src/boxed.rs | 26 ++-- library/alloc/src/boxed/thin.rs | 62 ++++---- .../alloc/src/collections/binary_heap/mod.rs | 13 +- .../alloc/src/collections/vec_deque/drain.rs | 22 +-- .../alloc/src/collections/vec_deque/mod.rs | 137 +++++++++--------- .../src/collections/vec_deque/spec_extend.rs | 28 ++-- library/alloc/src/ffi/c_str.rs | 25 ++-- library/alloc/src/str.rs | 19 +-- library/alloc/src/vec/into_iter.rs | 11 +- library/alloc/src/vec/mod.rs | 15 +- 10 files changed, 169 insertions(+), 189 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 67ca0b0870d1d..cb282d3b4e6e9 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2037,20 +2037,18 @@ impl Default for Box { #[inline] fn default() -> Self { let mut x: Box> = Box::new_uninit(); - // SAFETY: See within. - unsafe { - // SAFETY: `x` is valid for writing and has the same layout as `T`. - // If `T::default()` panics, dropping `x` will just deallocate the Box as `MaybeUninit` - // does not have a destructor. - // - // We use `ptr::write` as `MaybeUninit::write` creates - // extra stack copies of `T` in debug mode. - // - // See https://github.com/rust-lang/rust/issues/136043 for more context. - ptr::write(&raw mut *x as *mut T, T::default()); - // SAFETY: `x` was just initialized above. - x.assume_init() - } + + // SAFETY: `x` is valid for writing and has the same layout as `T`. + // If `T::default()` panics, dropping `x` will just deallocate the Box as `MaybeUninit` + // does not have a destructor. + // + // We use `ptr::write` as `MaybeUninit::write` creates + // extra stack copies of `T` in debug mode. + // + // See https://github.com/rust-lang/rust/issues/136043 for more context. + unsafe { ptr::write(&raw mut *x as *mut T, T::default()) }; + // SAFETY: `x` was just initialized above. + unsafe { x.assume_init() } } } diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index d3f9bbd791fd3..1972c24183d4d 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -334,23 +334,22 @@ impl WithHeader { let alloc_size = max(align_of::(), size_of::<::Metadata>()); - // SAFETY: See within. - unsafe { - // SAFETY: align is power of two because it is the maximum of two alignments. - let alloc: *mut u8 = const_allocate(alloc_size, alloc_align); + // SAFETY: align is power of two because it is the maximum of two alignments. + let alloc: *mut u8 = unsafe { const_allocate(alloc_size, alloc_align) }; - let metadata_offset = - alloc_size.checked_sub(size_of::<::Metadata>()).unwrap(); + let metadata_offset = + alloc_size.checked_sub(size_of::<::Metadata>()).unwrap(); + let metadata_ptr: *mut ::Metadata = // SAFETY: adding offset within the allocation. - let metadata_ptr: *mut ::Metadata = - alloc.add(metadata_offset).cast(); - // SAFETY: `*metadata_ptr` is within the allocation. + unsafe { alloc.add(metadata_offset).cast() }; + // SAFETY: `*metadata_ptr` is within the allocation. + unsafe { metadata_ptr.write(ptr::metadata::(ptr::dangling::() as *const Dyn)); - // SAFETY: valid heap allocation - const_make_global(alloc); - // SAFETY: we have just written the metadata. - &*metadata_ptr } + // SAFETY: valid heap allocation + unsafe { const_make_global(alloc) }; + // SAFETY: we have just written the metadata. + unsafe { &*metadata_ptr } }; let value_ptr = @@ -378,32 +377,29 @@ impl WithHeader { return; } - // SAFETY: See within. - unsafe { + let (layout, value_offset) = // SAFETY: Layout must have been computable if we're in drop - let (layout, value_offset) = - WithHeader::::alloc_layout(self.value_layout).unwrap_unchecked(); + unsafe { WithHeader::::alloc_layout(self.value_layout).unwrap_unchecked() }; - // Since we only allocate for non-ZSTs, the layout size cannot be zero. - debug_assert!(layout.size() != 0); - alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout); - } + // Since we only allocate for non-ZSTs, the layout size cannot be zero. + debug_assert!(layout.size() != 0); + // SAFETY: We own the allocation with `layout` at `ptr - value_offset`. + unsafe { alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout) }; } } - // SAFETY: See within. - unsafe { - // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. - let _guard = DropGuard { - ptr: self.0, - value_layout: Layout::for_value_raw(value), - _marker: PhantomData::, - }; + // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. + let _guard = DropGuard { + ptr: self.0, + // SAFETY: Caller ensures `value` is valid. + value_layout: unsafe { Layout::for_value_raw(value) }, + _marker: PhantomData::, + }; - // We only drop the value because the Pointee trait requires that the metadata is copy - // aka trivially droppable. - ptr::drop_in_place::(value); - } + // We only drop the value because the Pointee trait requires that the metadata is copy + // aka trivially droppable. + // SAFETY: We're the only droppers of `value` and it's not dropped again. + unsafe { ptr::drop_in_place::(value) }; } fn header(&self) -> *mut H { diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 2666d70d4df28..0fee6be8b3eb6 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -346,14 +346,11 @@ impl DerefMut for PeekMut<'_, T, A> { // // This is technique is described throughout several other places in // the standard library as "leak amplification". - // SAFETY: See within. - unsafe { - // SAFETY: len > 1 so len != 0. - self.original_len = Some(NonZero::new_unchecked(len)); - // SAFETY: len > 1 so all this does for now is leak elements, - // which is safe. - self.heap.data.set_len(1); - } + // SAFETY: len > 1 so len != 0. + self.original_len = Some(unsafe { NonZero::new_unchecked(len) }); + // SAFETY: len > 1 so all this does for now is leak elements, + // which is safe. + unsafe { self.heap.data.set_len(1) }; } // SAFETY: PeekMut is only instantiated for non-empty heaps diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index 2b1e673be25f7..923c79dcbd41b 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -99,17 +99,17 @@ impl Drop for Drain<'_, T, A> { let guard = DropGuard(self); if mem::needs_drop::() && guard.0.remaining != 0 { - // SAFETY: See within. - unsafe { - // SAFETY: We just checked that `self.remaining != 0`. - let (front, back) = guard.0.as_slices(); - // since idx is a logical index, we don't need to worry about wrapping. - guard.0.idx += front.len(); - guard.0.remaining -= front.len(); - ptr::drop_in_place(front); - guard.0.remaining = 0; - ptr::drop_in_place(back); - } + // SAFETY: We just checked that `self.remaining != 0`. + let (front, back) = unsafe { guard.0.as_slices() }; + // since idx is a logical index, we don't need to worry about wrapping. + guard.0.idx += front.len(); + guard.0.remaining -= front.len(); + // SAFETY: This can't have been dropped before since + // `idx` & `remaining` track what's been dropped. + unsafe { ptr::drop_in_place(front) }; + guard.0.remaining = 0; + // SAFETY: Ditto. + unsafe { ptr::drop_in_place(back) }; } // Dropping `guard` handles moving the remaining elements into place. diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 40a28f9ba6c44..299d302731dfd 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3626,21 +3626,21 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; - // SAFETY: See within. - unsafe { - // SAFETY: - // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. - // - Ranges are in bounds: guaranteed by the caller. - let ranges = self.nonoverlapping_ranges(src, dst, count, self.head); - - // `len` is updated after every clone to prevent leaking and - // leave the deque in the right state when a clone implementation panics - - for (src, dst, count) in ranges { - for offset in 0..count { - dst.add(offset).write((*src.add(offset)).clone()); - self.len += 1; - } + // SAFETY: + // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. + // - Ranges are in bounds: guaranteed by the caller. + let ranges = unsafe { self.nonoverlapping_ranges(src, dst, count, self.head) }; + + // `len` is updated after every clone to prevent leaking and + // leave the deque in the right state when a clone implementation panics + + for (src, dst, count) in ranges { + for offset in 0..count { + // SAFETY: The allocations of `dst` and `src` go up to `count` elems, + // and `nonoverlapping_ranges` ensures `dst` and `src` are valid + // for writes and reads respectively. + unsafe { dst.add(offset).write((*src.add(offset)).clone()) }; + self.len += 1; } } } @@ -3653,46 +3653,49 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); let cap = self.capacity(); - // SAFETY: See within. - unsafe { - // SAFETY: - // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. - // - Ranges are in bounds: guaranteed by the caller. - let ranges = self.nonoverlapping_ranges(src, dst, count, new_head); - - // Cloning is done in reverse because we prepend to the front of the deque, - // we can't get holes in the *logical* buffer. - // `head` and `len` are updated after every clone to prevent leaking and - // leave the deque in the right state when a clone implementation panics - - // Clone the first range - let (src, dst, count) = ranges[1]; - for offset in (0..count).rev() { - dst.add(offset).write((*src.add(offset)).clone()); - self.head = self.head.sub(1); - self.len += 1; + // SAFETY: + // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. + // - Ranges are in bounds: guaranteed by the caller. + let ranges = self.nonoverlapping_ranges(src, dst, count, new_head); + + // Cloning is done in reverse because we prepend to the front of the deque, + // we can't get holes in the *logical* buffer. + // `head` and `len` are updated after every clone to prevent leaking and + // leave the deque in the right state when a clone implementation panics + + // Clone the first range + let (src, dst, count) = ranges[1]; + for offset in (0..count).rev() { + // SAFETY: Untriaged. + unsafe { dst.add(offset).write((*src.add(offset)).clone()) }; + // SAFETY: Untriaged. + self.head = unsafe { self.head.sub(1) }; + self.len += 1; + } + + // Clone the second range + let (src, dst, count) = ranges[0]; + let mut iter = (0..count).rev(); + if let Some(offset) = iter.next() { + // SAFETY: Untriaged. + unsafe { dst.add(offset).write((*src.add(offset)).clone()) }; + // After the first clone of the second range, wrap `head` around + if self.head.is_zero() { + // SAFETY: the wrapped index may be temporarily equal to the capacity even if it + // is not zero, because we subtract it one line below. + // FIXME: should `from_arbitrary_number` be unsafe? its docs imply so... + self.head = WrappedIndex::from_arbitrary_number(cap); } + // SAFETY: Untriaged. + self.head = unsafe { self.head.sub(1) }; + self.len += 1; - // Clone the second range - let (src, dst, count) = ranges[0]; - let mut iter = (0..count).rev(); - if let Some(offset) = iter.next() { - dst.add(offset).write((*src.add(offset)).clone()); - // After the first clone of the second range, wrap `head` around - if self.head.is_zero() { - // SAFETY: the wrapped index may be temporarily equal to the capacity even if it - // is not zero, because we subtract it one line below. - self.head = WrappedIndex::from_arbitrary_number(cap); - } + // Continue like normal + for offset in iter { + // SAFETY: Untriaged. + unsafe { dst.add(offset).write((*src.add(offset)).clone()) }; self.head = self.head.sub(1); self.len += 1; - - // Continue like normal - for offset in iter { - dst.add(offset).write((*src.add(offset)).clone()); - self.head = self.head.sub(1); - self.len += 1; - } } } } @@ -3705,15 +3708,13 @@ impl SpecExtendFromWithin for VecDeque { let count = src.end - src.start; let src = src.start; - // SAFETY: See within. - unsafe { - // SAFETY: - // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. - // - Ranges are in bounds: guaranteed by the caller. - let ranges = self.nonoverlapping_ranges(src, dst, count, self.head); - for (src, dst, count) in ranges { - ptr::copy_nonoverlapping(src, dst, count); - } + // SAFETY: + // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. + // - Ranges are in bounds: guaranteed by the caller. + let ranges = unsafe { self.nonoverlapping_ranges(src, dst, count, self.head) }; + for (src, dst, count) in ranges { + // SAFETY: Ditto. + unsafe { ptr::copy_nonoverlapping(src, dst, count) }; } // SAFETY: @@ -3728,15 +3729,13 @@ impl SpecExtendFromWithin for VecDeque { let new_head = self.wrap_sub(self.head, count); - // SAFETY: See within. - unsafe { - // SAFETY: - // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. - // - Ranges are in bounds: guaranteed by the caller. - let ranges = self.nonoverlapping_ranges(src, dst, count, new_head); - for (src, dst, count) in ranges { - ptr::copy_nonoverlapping(src, dst, count); - } + // SAFETY: + // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. + // - Ranges are in bounds: guaranteed by the caller. + let ranges = unsafe { self.nonoverlapping_ranges(src, dst, count, new_head) }; + for (src, dst, count) in ranges { + // SAFETY: Ditto. + unsafe { ptr::copy_nonoverlapping(src, dst, count) }; } // SAFETY: diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs index cb3f39942339f..782cd1e908240 100644 --- a/library/alloc/src/collections/vec_deque/spec_extend.rs +++ b/library/alloc/src/collections/vec_deque/spec_extend.rs @@ -216,16 +216,16 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront> f } self.reserve(iter.remaining); - // SAFETY: See within. + + // SAFETY: iter.remaining != 0. + let (left, right) = unsafe { iter.as_slices() }; + // SAFETY: + // - `iter.remaining` space was reserved, `iter.remaining == left.len() + right.len()`. + // - The elements in `left` and `right` are forgotten after these calls. unsafe { - // SAFETY: iter.remaining != 0. - let (left, right) = iter.as_slices(); - // SAFETY: - // - `iter.remaining` space was reserved, `iter.remaining == left.len() + right.len()`. - // - The elements in `left` and `right` are forgotten after these calls. prepend_reversed(self, &*left); - prepend_reversed(self, &*right); - } + prepend_reversed(self, &*right) + }; iter.idx += iter.remaining; iter.remaining = 0; @@ -244,13 +244,13 @@ impl<'a, T, A1: Allocator, A2: Allocator> SpecExtendFront>> for CString { /// copying nor checking for inner nul bytes. #[inline] fn from(v: Vec>) -> CString { - // SAFETY: See within. - unsafe { - // Transmute `Vec>` to `Vec`. - let v: Vec = { - // SAFETY: - // - transmuting between `NonZero` and `u8` is sound; - // - `alloc::Layout> == alloc::Layout`. - let (ptr, len, cap): (*mut NonZero, _, _) = Vec::into_raw_parts(v); - Vec::from_raw_parts(ptr.cast::(), len, cap) - }; - // SAFETY: `v` cannot contain nul bytes, given the type-level - // invariant of `NonZero`. - Self::_from_vec_unchecked(v) - } + // Transmute `Vec>` to `Vec`. + let v: Vec = { + let (ptr, len, cap): (*mut NonZero, _, _) = Vec::into_raw_parts(v); + // SAFETY: + // - transmuting between `NonZero` and `u8` is sound; + // - `alloc::Layout> == alloc::Layout`. + unsafe { Vec::from_raw_parts(ptr.cast::(), len, cap) } + }; + // SAFETY: `v` cannot contain nul bytes, given the type-level + // invariant of `NonZero`. + unsafe { Self::_from_vec_unchecked(v) } } } diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index b1cccf7c234c8..6bdf2577aa074 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -994,20 +994,17 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; } - // SAFETY: See within. - unsafe { - // SAFETY: ascii_prefix_len bytes have been initialized above - out.set_len(ascii_prefix_len); + // SAFETY: ascii_prefix_len bytes have been initialized above + unsafe { out.set_len(ascii_prefix_len) }; - // SAFETY: We have written only valid ascii to the output vec - let ascii_string = String::from_utf8_unchecked(out); + // SAFETY: We have written only valid ascii to the output vec + let ascii_string = unsafe { String::from_utf8_unchecked(out) }; - // SAFETY: we know this is a valid char boundary - // since we only skipped over leading ascii bytes - let rest = core::str::from_utf8_unchecked(slice); + // SAFETY: we know this is a valid char boundary + // since we only skipped over leading ascii bytes + let rest = unsafe { core::str::from_utf8_unchecked(slice) }; - (ascii_string, rest) - } + (ascii_string, rest) } #[inline] #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index c71ef6dddc620..cf458e9f8ea94 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -201,13 +201,10 @@ impl IntoIter { /// memory if there are any remaining elements. #[inline] unsafe fn dealloc_only(&mut self) { - // SAFETY: See within. - unsafe { - // SAFETY: our caller promises not to touch `*self` again - let alloc = ManuallyDrop::take(&mut self.alloc); - // RawVec handles deallocation - let _ = RawVec::from_nonnull_in(self.buf, self.cap, alloc); - } + // SAFETY: our caller promises not to touch `*self` again. + let alloc = unsafe { ManuallyDrop::take(&mut self.alloc) }; + // SAFETY: We're using this to deallocate a preexisting `RawVec`. + let _ = unsafe { RawVec::from_nonnull_in(self.buf, self.cap, alloc) }; } #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index c52701e0a712e..3eadecb194e6b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2851,15 +2851,14 @@ impl Vec { return Err(value); } - // SAFETY: See within. - unsafe { - let end = self.as_mut_ptr().add(self.len); - ptr::write(end, value); - self.len += 1; + // SAFETY: Untriaged. + let end = unsafe { self.as_mut_ptr().add(self.len) }; + // SAFETY: Untriaged. + unsafe { ptr::write(end, value) }; + self.len += 1; - // SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference. - Ok(&mut *end) - } + // SAFETY: We just wrote a value to the pointer that will live the lifetime of the reference. + Ok(unsafe { &mut *end }) } /// Removes the last element from a vector and returns it, or [`None`] if it From 95eb76c12c8d107ea03a793cbfee731cc564bec4 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Thu, 13 Aug 2026 00:36:20 +0200 Subject: [PATCH 6/8] fixup some safety comments --- .../alloc/src/collections/binary_heap/mod.rs | 8 ++++++-- library/alloc/src/collections/btree/mem.rs | 2 +- .../alloc/src/collections/vec_deque/mod.rs | 19 +++++++++---------- library/alloc/src/sync.rs | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 0fee6be8b3eb6..e087c274cf0e3 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -1530,11 +1530,13 @@ struct Hole<'a, T: 'a> { impl<'a, T> Hole<'a, T> { /// Creates a new `Hole` at index `pos`. /// - /// Unsafe because pos must be within the data slice. + /// # Safety + /// + /// `pos` must be within the data slice. #[inline] unsafe fn new(data: &'a mut [T], pos: usize) -> Self { debug_assert!(pos < data.len()); - // SAFETY: pos should be inside the slice + // SAFETY: Caller ensures pos is inside the slice. let elt = unsafe { ptr::read(data.get_unchecked(pos)) }; Hole { data, elt: ManuallyDrop::new(elt), pos } } @@ -1553,6 +1555,7 @@ impl<'a, T> Hole<'a, T> { /// Returns a reference to the element at `index`. /// /// # Safety + /// /// `index` must be within the data slice and not equal to the current position. #[inline] unsafe fn get(&self, index: usize) -> &T { @@ -1565,6 +1568,7 @@ impl<'a, T> Hole<'a, T> { /// Move hole to new location /// /// # Safety + /// /// `index` must be within the data slice and not equal to the current position. #[inline] unsafe fn move_to(&mut self, index: usize) { diff --git a/library/alloc/src/collections/btree/mem.rs b/library/alloc/src/collections/btree/mem.rs index a0e9e173757a0..ad86e9422d974 100644 --- a/library/alloc/src/collections/btree/mem.rs +++ b/library/alloc/src/collections/btree/mem.rs @@ -23,7 +23,7 @@ pub(super) fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { } } let guard = PanicGuard; - // SAFETY: v is valid for reads. + // SAFETY: v is valid for reads and we write a new value before returning. let value = unsafe { ptr::read(v) }; let (new_value, ret) = change(value); // SAFETY: new_value is T and v is valid for writes. diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 299d302731dfd..e0a68d2643ce8 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1893,9 +1893,8 @@ impl VecDeque { // are valid ranges into the physical buffer, so // it's ok to pass them to `buffer_range` and // dereference the result. - let a = unsafe { &*self.buffer_range(a_range) }; - // SAFETY: As above. - let b = unsafe { &*self.buffer_range(b_range) }; + let (a, b) = unsafe { (&*self.buffer_range(a_range), &*self.buffer_range(b_range)) }; + Iter::new(a.iter(), b.iter()) } @@ -1930,13 +1929,13 @@ impl VecDeque { R: RangeBounds, { let (a_range, b_range) = self.slice_ranges(range, self.len); - // SAFETY: The ranges returned by `slice_ranges` - // are valid ranges into the physical buffer, so - // it's ok to pass them to `buffer_range` and - // dereference the result. - let a = unsafe { &mut *self.buffer_range(a_range) }; - // SAFETY: As above. - let b = unsafe { &mut *self.buffer_range(b_range) }; + let (a, b) = + // SAFETY: The ranges returned by `slice_ranges` + // are valid ranges into the physical buffer, so + // it's ok to pass them to `buffer_range` and + // dereference the result. + unsafe { (&mut *self.buffer_range(a_range), &mut *self.buffer_range(b_range)) }; + IterMut::new(a.iter_mut(), b.iter_mut()) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index fd34974081a5a..08665a14bac28 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4945,7 +4945,7 @@ impl UniqueArc { #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); - // SAFETY: Pointer is valid for reads and won't be double-dropped. + // SAFETY: Pointer is valid for reads and only read once. (this.ptr, unsafe { ptr::read(&this.alloc) }) } From a9b1419d64bf84060381bd04af689ed2ae235100 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Thu, 13 Aug 2026 00:53:44 +0200 Subject: [PATCH 7/8] oepsje woepsje --- library/alloc/src/collections/vec_deque/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index e0a68d2643ce8..22bbc247ad025 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3655,7 +3655,7 @@ impl SpecExtendFromWithin for VecDeque { // SAFETY: // - Ranges do not overlap: src entirely spans initialized values, dst entirely spans uninitialized values. // - Ranges are in bounds: guaranteed by the caller. - let ranges = self.nonoverlapping_ranges(src, dst, count, new_head); + let ranges = unsafe { self.nonoverlapping_ranges(src, dst, count, new_head) }; // Cloning is done in reverse because we prepend to the front of the deque, // we can't get holes in the *logical* buffer. @@ -3693,7 +3693,8 @@ impl SpecExtendFromWithin for VecDeque { for offset in iter { // SAFETY: Untriaged. unsafe { dst.add(offset).write((*src.add(offset)).clone()) }; - self.head = self.head.sub(1); + // SAFETY: Untriaged. + self.head = unsafe { self.head.sub(1) }; self.len += 1; } } From 0c8e275d5c6fd2b444778b7248a298423ecc7d91 Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Thu, 13 Aug 2026 01:54:11 +0200 Subject: [PATCH 8/8] more safety comments fixed or broken up --- library/alloc/src/collections/btree/node.rs | 24 ++++++++----------- .../alloc/src/collections/vec_deque/mod.rs | 10 ++++---- library/alloc/src/io/cursor.rs | 5 ++-- library/alloc/src/vec/mod.rs | 13 +++++----- 4 files changed, 24 insertions(+), 28 deletions(-) diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index e9957b8e5ae66..dc0045e7a98f8 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -86,13 +86,11 @@ impl LeafNode { /// Creates a new boxed `LeafNode`. fn new(alloc: A) -> Box { let mut leaf = Box::new_uninit_in(alloc); - // SAFETY: Untriaged. - unsafe { - // SAFETY: `leaf` points to a `LeafNode` - LeafNode::init(leaf.as_mut_ptr()); - // SAFETY: `leaf` was just initialized - leaf.assume_init() - } + + // SAFETY: `leaf` points to a `LeafNode`. + unsafe { LeafNode::init(leaf.as_mut_ptr()) }; + // SAFETY: `leaf` was just initialized. + unsafe { leaf.assume_init() } } } @@ -121,13 +119,11 @@ impl InternalNode { /// such an edge. unsafe fn new(alloc: A) -> Box { let mut node = Box::::new_uninit_in(alloc); - // SAFETY: Untriaged. - unsafe { - // SAFETY: argument points to the `node.data` `LeafNode` - LeafNode::init(&raw mut (*node.as_mut_ptr()).data); - // SAFETY: `node.data` was just initialized and `node.edges` is MaybeUninit. - node.assume_init() - } + + // SAFETY: argument points to the `node.data` `LeafNode`. + unsafe { LeafNode::init(&raw mut (*node.as_mut_ptr()).data) }; + // SAFETY: `node.data` was just initialized and `node.edges` is MaybeUninit. + unsafe { node.assume_init() } } } diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 22bbc247ad025..60deeeb73d9ea 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1324,9 +1324,10 @@ impl VecDeque { // [. . . . . . . . o o o o o o o . ] // H L // [o o o o o o o . ] - // SAFETY: Untriaged. + // + // SAFETY: `self.head >= target_cap >= self.len`, therefore these accesses + // do not overlap. unsafe { - // nonoverlapping because `self.head >= target_cap >= self.len`. self.copy_nonoverlapping(self.head, WrappedIndex::zero(), self.len); } self.head = WrappedIndex::zero(); @@ -1423,10 +1424,9 @@ impl VecDeque { // There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`), // and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`). - // SAFETY: Untriaged. + // SAFETY: The old tail and the new tail can't overlap because the head slice lies + // between them. The head slice ends at `target_cap`, so that's where we copy to. unsafe { - // The old tail and the new tail can't overlap because the head slice lies between them. The - // head slice ends at `target_cap`, so that's where we copy to. self.copy_nonoverlapping( WrappedIndex::zero(), WrappedIndex::from_arbitrary_number(target_cap), diff --git a/library/alloc/src/io/cursor.rs b/library/alloc/src/io/cursor.rs index ef213a0069f3f..7e05a079fc054 100644 --- a/library/alloc/src/io/cursor.rs +++ b/library/alloc/src/io/cursor.rs @@ -238,10 +238,9 @@ where let buf_len = bufs.iter().fold(0usize, |a, b| a.saturating_add(b.len())); let mut pos = reserve_and_pad(pos_mut, vec, buf_len)?; - // Write the buf then progress the vec forward if necessary - // Safety: we have ensured that the capacity is available + // Write the buf then progress the vec forward if necessary. + // SAFETY: We have ensured that the capacity is available // and that all bytes get written up to the last pos - // SAFETY: Untriaged. unsafe { for buf in bufs { pos = vec_write_all_unchecked(pos, vec, buf); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3eadecb194e6b..57b90367db07d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2695,14 +2695,15 @@ impl Vec { let mut first_duplicate_idx: usize = 1; let start = self.as_mut_ptr(); while first_duplicate_idx != len { - // SAFETY: Untriaged. - let found_duplicate = unsafe { - // SAFETY: first_duplicate always in range [1..len) + let found_duplicate = { + // SAFETY: first_duplicate always in range [1..len). // Note that we start iteration from 1 so we never overflow. - let prev = start.add(first_duplicate_idx.wrapping_sub(1)); - let current = start.add(first_duplicate_idx); + let prev = unsafe { start.add(first_duplicate_idx.wrapping_sub(1)) }; + // SAFETY: Untriaged. + let current = unsafe { start.add(first_duplicate_idx) }; // We explicitly say in docs that references are reversed. - same_bucket(&mut *current, &mut *prev) + // SAFETY: Untriaged. + unsafe { same_bucket(&mut *current, &mut *prev) } }; if found_duplicate { break;