rust-lang/rust · #162102
`alloc` crate: shrink undocumented `unsafe` blocks
library/alloc/src/boxed/thin.rs53 + / 45 −
@@ -165,10 +165,10 @@ impl<T: ?Sized> DerefMut for ThinBox<T> { #[unstable(feature = "thin_box", issue = "92791")] impl<T: ?Sized> Drop for ThinBox<T> { fn drop(&mut self) {+ let value = self.deref_mut();+ let value = value as *mut T; // ignore-tidy-undocumented-unsafe unsafe {- let value = self.deref_mut();- let value = value as *mut T; self.with_header().drop::<T>(value); } }@@ -240,34 +240,38 @@ impl<H> WithHeader<H> { alloc::handle_alloc_error(Layout::new::<()>()); }; - // ignore-tidy-undocumented-unsafe- 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- // alignment for both `T` and `H`.- let ptr = if layout.size() == 0 {- // Some paranoia checking, mostly so that the ThinBox tests are- // more able to catch issues.- debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);- layout.dangling_ptr()- } else {- let ptr = alloc::alloc(layout);- if ptr.is_null() {- alloc::handle_alloc_error(layout);- }- // Safety:- // - The size is at least `aligned_header_size`.+ // 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+ // alignment for both `T` and `H`.+ let ptr = if layout.size() == 0 {+ // Some paranoia checking, mostly so that the ThinBox tests are+ // more able to catch issues.+ debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);+ layout.dangling_ptr()+ } else {+ // ignore-tidy-undocumented-unsafe+ let ptr = unsafe { alloc::alloc(layout) };+ if ptr.is_null() {+ alloc::handle_alloc_error(layout);+ }+ // SAFETY:+ // - The size is at least `aligned_header_size`.+ unsafe { let ptr = ptr.add(value_offset) as *mut _; NonNull::new_unchecked(ptr)- };+ }+ }; - let result = WithHeader(ptr, PhantomData);+ let result = WithHeader(ptr, PhantomData);++ // ignore-tidy-undocumented-unsafe+ unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value);-- result }++ result } /// Non-panicking version of `new`.@@ -278,35 +282,39 @@ impl<H> WithHeader<H> { return Err(core::alloc::AllocError); }; - // ignore-tidy-undocumented-unsafe- 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- // alignment for both `T` and `H`.- let ptr = if layout.size() == 0 {- // Some paranoia checking, mostly so that the ThinBox tests are- // more able to catch issues.- debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);- layout.dangling_ptr()- } else {- let ptr = alloc::alloc(layout);- if ptr.is_null() {- return Err(core::alloc::AllocError);- }-- // Safety:- // - The size is at least `aligned_header_size`.+ // 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+ // alignment for both `T` and `H`.+ let ptr = if layout.size() == 0 {+ // Some paranoia checking, mostly so that the ThinBox tests are+ // more able to catch issues.+ debug_assert!(value_offset == 0 && T::IS_ZST && H::IS_ZST);+ layout.dangling_ptr()+ } else {+ // ignore-tidy-undocumented-unsafe+ let ptr = unsafe { alloc::alloc(layout) };+ if ptr.is_null() {+ return Err(core::alloc::AllocError);+ }++ // SAFETY:+ // - The size is at least `aligned_header_size`.+ unsafe { let ptr = ptr.add(value_offset) as *mut _; NonNull::new_unchecked(ptr)- };+ }+ };++ let result = WithHeader(ptr, PhantomData); - let result = WithHeader(ptr, PhantomData);+ // ignore-tidy-undocumented-unsafe+ unsafe { ptr::write(result.header(), header); ptr::write(result.value().cast(), value);-- Ok(result) }++ Ok(result) } // `Dyn` is `?Sized` type like `[u32]`, and `T` is ZST type like `[u32; 0]`.library/alloc/src/collections/binary_heap/mod.rs2 + / 2 −
@@ -1574,9 +1574,9 @@ 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());+ let ptr = self.data.as_mut_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let ptr = self.data.as_mut_ptr(); let index_ptr: *const _ = ptr.add(index); let hole_ptr = ptr.add(self.pos); ptr::copy_nonoverlapping(index_ptr, hole_ptr, 1);@@ -1589,9 +1589,9 @@ impl<T> Drop for Hole<'_, T> { #[inline] fn drop(&mut self) { // fill the hole again+ let pos = self.pos; // ignore-tidy-undocumented-unsafe unsafe {- let pos = self.pos; ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1); } }library/alloc/src/collections/btree/map.rs3 + / 3 −
@@ -280,10 +280,10 @@ impl<K: Clone, V: Clone, A: AllocatorClone> Clone for BTreeMap<K, V, A> { // We can't destructure subtree directly // because BTreeMap implements Drop- // ignore-tidy-undocumented-unsafe- let (subroot, sublength) = unsafe {+ let (subroot, sublength) = { let subtree = ManuallyDrop::new(subtree);- let root = ptr::read(&subtree.root);+ // ignore-tidy-undocumented-unsafe+ let root = unsafe { ptr::read(&subtree.root) }; let length = subtree.length; (root, length) };library/alloc/src/collections/btree/node.rs8 + / 8 −
@@ -1875,11 +1875,11 @@ pub(super) mod marker { /// # Safety /// The slice has more than `idx` elements. unsafe fn slice_insert<T>(slice: &mut [MaybeUninit<T>], idx: usize, val: T) {+ let len = slice.len();+ debug_assert!(len > idx);+ let slice_ptr = slice.as_mut_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let len = slice.len();- debug_assert!(len > idx);- let slice_ptr = slice.as_mut_ptr(); if len > idx + 1 { ptr::copy(slice_ptr.add(idx), slice_ptr.add(idx + 1), len - idx - 1); }@@ -1893,11 +1893,11 @@ unsafe fn slice_insert<T>(slice: &mut [MaybeUninit<T>], idx: usize, val: T) { /// # Safety /// The slice has more than `idx` elements. unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T {+ let len = slice.len();+ debug_assert!(idx < len);+ let slice_ptr = slice.as_mut_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let len = slice.len();- debug_assert!(idx < len);- let slice_ptr = slice.as_mut_ptr(); let ret = (*slice_ptr.add(idx)).assume_init_read(); ptr::copy(slice_ptr.add(idx + 1), slice_ptr.add(idx), len - idx - 1); ret@@ -1909,9 +1909,9 @@ unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T { /// # Safety /// The slice has at least `distance` elements. unsafe fn slice_shl<T>(slice: &mut [MaybeUninit<T>], distance: usize) {+ let slice_ptr = slice.as_mut_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let slice_ptr = slice.as_mut_ptr(); ptr::copy(slice_ptr.add(distance), slice_ptr, slice.len() - distance); } }@@ -1921,9 +1921,9 @@ unsafe fn slice_shl<T>(slice: &mut [MaybeUninit<T>], distance: usize) { /// # Safety /// The slice has at least `distance` elements. unsafe fn slice_shr<T>(slice: &mut [MaybeUninit<T>], distance: usize) {+ let slice_ptr = slice.as_mut_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let slice_ptr = slice.as_mut_ptr(); ptr::copy(slice_ptr, slice_ptr.add(distance), slice.len() - distance); } }library/alloc/src/collections/linked_list.rs28 + / 28 −
@@ -1679,20 +1679,20 @@ 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<T>) {+ let Some((splice_head, splice_tail, splice_len)) = list.detach_all_nodes() else {+ return;+ }; // ignore-tidy-undocumented-unsafe unsafe {- let Some((splice_head, splice_tail, splice_len)) = list.detach_all_nodes() else {- return;- }; let node_next = match self.current { None => self.list.head, Some(node) => node.as_ref().next, }; self.list.splice_nodes(self.current, node_next, splice_head, splice_tail, splice_len);- if self.current.is_none() {- // The "ghost" non-element's index has changed.- self.index = self.list.len;- }+ }+ if self.current.is_none() {+ // The "ghost" non-element's index has changed.+ self.index = self.list.len; } } @@ -1702,19 +1702,19 @@ 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<T>) {+ let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {+ Some(parts) => parts,+ _ => return,+ }; // ignore-tidy-undocumented-unsafe unsafe {- let (splice_head, splice_tail, splice_len) = match list.detach_all_nodes() {- Some(parts) => parts,- _ => return,- }; let node_prev = match self.current { None => self.list.tail, Some(node) => node.as_ref().prev, }; self.list.splice_nodes(node_prev, self.current, splice_head, splice_tail, splice_len);- self.index += splice_len; }+ self.index += splice_len; } } @@ -1725,19 +1725,19 @@ 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) {+ let spliced_node =+ Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; // ignore-tidy-undocumented-unsafe unsafe {- let spliced_node =- Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; let node_next = match self.current { None => self.list.head, Some(node) => node.as_ref().next, }; self.list.splice_nodes(self.current, node_next, spliced_node, spliced_node, 1);- if self.current.is_none() {- // The "ghost" non-element's index has changed.- self.index = self.list.len;- }+ }+ if self.current.is_none() {+ // The "ghost" non-element's index has changed.+ self.index = self.list.len; } } @@ -1747,17 +1747,17 @@ 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) {+ let spliced_node =+ Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; // ignore-tidy-undocumented-unsafe unsafe {- let spliced_node =- Box::into_non_null_with_allocator(Box::new_in(Node::new(item), &self.list.alloc)).0; let node_prev = match self.current { None => self.list.tail, Some(node) => node.as_ref().prev, }; self.list.splice_nodes(node_prev, self.current, spliced_node, spliced_node, 1);- self.index += 1; }+ self.index += 1; } /// Removes the current element from the `LinkedList`.@@ -1799,14 +1799,14 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { unlinked_node.as_mut().prev = None; unlinked_node.as_mut().next = None;- Some(LinkedList {- head: Some(unlinked_node),- tail: Some(unlinked_node),- len: 1,- alloc: self.list.alloc.clone(),- marker: PhantomData,- }) }+ Some(LinkedList {+ head: Some(unlinked_node),+ tail: Some(unlinked_node),+ len: 1,+ alloc: self.list.alloc.clone(),+ marker: PhantomData,+ }) } /// Splits the list into two after the current element. This will return alibrary/alloc/src/collections/vec_deque/mod.rs14 + / 12 −
@@ -1455,18 +1455,19 @@ impl<T, A: Allocator> VecDeque<T, A> { #[doc(alias = "retain_front")] #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) {+ if len >= self.len {+ return;+ }++ let (front, back) = self.as_mut_slices();+ // 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 unsafe {- if len >= self.len {- return;- }-- let (front, back) = self.as_mut_slices(); if len > front.len() { let begin = len - front.len(); let drop_back = back.get_unchecked_mut(begin..) as *mut _;@@ -1508,14 +1509,15 @@ impl<T, A: Allocator> VecDeque<T, A> { #[doc(alias = "truncate_front")] #[stable(feature = "vec_deque_truncate_front", since = "1.99.0")] pub fn retain_back(&mut self, len: usize) {+ if len >= self.len {+ // No action is taken+ return;+ }++ let (front, back) = self.as_mut_slices();+ // ignore-tidy-undocumented-unsafe unsafe {- if len >= self.len {- // No action is taken- return;- }-- let (front, back) = self.as_mut_slices(); if len > back.len() { // The 'back' slice remains unchanged. // front.len() + back.len() == self.len, so 'end' is non-negative@@ -2773,9 +2775,9 @@ impl<T, A: Allocator> VecDeque<T, A> { } self.reserve(other.len);+ let (left, right) = other.as_slices(); // ignore-tidy-undocumented-unsafe unsafe {- let (left, right) = other.as_slices(); self.copy_slice(self.to_wrapped_index(self.len), left); // no overflow, because self.capacity() >= old_cap + left.len() >= self.len + left.len() self.copy_slice(self.to_wrapped_index(self.len + left.len()), right);library/alloc/src/collections/vec_deque/spec_extend.rs2 + / 2 −
@@ -86,8 +86,8 @@ impl<T, A1: Allocator, A2: Allocator> SpecExtend<T, vec::IntoIter<T, A2>> for Ve // ignore-tidy-undocumented-unsafe unsafe { self.copy_slice(self.to_wrapped_index(self.len), slice);- self.len += slice.len(); }+ self.len += slice.len(); iterator.forget_remaining_elements_and_dealloc(); } }@@ -113,8 +113,8 @@ where // ignore-tidy-undocumented-unsafe unsafe { self.copy_slice(self.to_wrapped_index(self.len), slice);- self.len += slice.len(); }+ self.len += slice.len(); } } library/alloc/src/collections/vec_deque/splice.rs2 + / 2 −
@@ -64,10 +64,10 @@ impl<I: Iterator, A: Allocator> 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. + let tail_len = self.drain.tail_len; // #elements behind the drain+ // ignore-tidy-undocumented-unsafe unsafe {- let tail_len = self.drain.tail_len; // #elements behind the drain- if tail_len == 0 { self.drain.deque.as_mut().extend(self.replace_with.by_ref()); return;library/alloc/src/rc.rs1 + / 1 −
@@ -2395,9 +2395,9 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { #[cfg(not(no_global_oom_handling))] fn from_box_in(src: Box<T, A>) -> Rc<T, A> {+ let value_size = size_of_val(&*src); // ignore-tidy-undocumented-unsafe unsafe {- let value_size = size_of_val(&*src); let ptr = Self::allocate_for_ptr_in(&*src, Box::allocator(&src)); // Copy value as byteslibrary/alloc/src/slice.rs3 + / 5 −
@@ -474,12 +474,10 @@ impl<T> [T] { #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {+ let len = self.len();+ let (b, alloc) = Box::into_raw_with_allocator(self); // ignore-tidy-undocumented-unsafe- unsafe {- let len = self.len();- let (b, alloc) = Box::into_raw_with_allocator(self);- Vec::from_raw_parts_in(b as *mut T, len, len, alloc)- }+ unsafe { Vec::from_raw_parts_in(b as *mut T, len, len, alloc) } } /// Creates a vector by copying a slice `n` times.library/alloc/src/str.rs2 + / 2 −
@@ -181,10 +181,10 @@ where result.extend_from_slice(first); + let pos = result.len();+ debug_assert!(reserved_len >= pos); // ignore-tidy-undocumented-unsafe unsafe {- let pos = result.len();- debug_assert!(reserved_len >= pos); let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); // Convert the separator and slices to slices of MaybeUninitlibrary/alloc/src/sync.rs1 + / 1 −
@@ -860,9 +860,9 @@ impl<T, A: Allocator> Arc<T, A> { // Now we can properly initialize the inner value and turn our weak // reference into a strong reference.+ let inner = init_ptr.as_ptr(); // ignore-tidy-undocumented-unsafe unsafe {- let inner = init_ptr.as_ptr(); ptr::write(&raw mut (*inner).data, data); // The above write to the data field must be visible to any threads whichlibrary/alloc/src/vec/in_place_collect.rs4 + / 4 −
@@ -340,12 +340,12 @@ fn write_in_place_with_drop<T>( src_end: *const T, ) -> impl FnMut(InPlaceDrop<T>, T) -> Result<InPlaceDrop<T>, !> { move |mut sink, item| {+ // the InPlaceIterable contract cannot be verified precisely here since+ // try_fold has an exclusive reference to the source pointer+ // all we can do is check if it's still in range+ debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); // ignore-tidy-undocumented-unsafe unsafe {- // the InPlaceIterable contract cannot be verified precisely here since- // try_fold has an exclusive reference to the source pointer- // all we can do is check if it's still in range- debug_assert!(sink.dst as *const _ <= src_end, "InPlaceIterable contract violation"); ptr::write(sink.dst, item); // Since this executes user code which can panic we have to bump the pointer // after each step.library/alloc/src/vec/mod.rs9 + / 9 −
@@ -1733,10 +1733,10 @@ impl<T, A: Allocator> Vec<T, A> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] pub fn into_boxed_slice(mut self) -> Box<[T], A> {+ self.shrink_to_fit();+ let me = ManuallyDrop::new(self); // ignore-tidy-undocumented-unsafe unsafe {- self.shrink_to_fit();- let me = ManuallyDrop::new(self); let buf = ptr::read(&me.buf); let len = me.len(); buf.into_box(len).assume_init()@@ -2449,10 +2449,10 @@ impl<T, A: Allocator> Vec<T, A> { if index >= len { return None; }+ // infallible+ let ret; // ignore-tidy-undocumented-unsafe unsafe {- // infallible- let ret; { // the place we are taking from. let ptr = self.as_mut_ptr().add(index);@@ -2464,8 +2464,8 @@ impl<T, A: Allocator> Vec<T, A> { ptr::copy(ptr.add(1), ptr, len - index - 1); } self.set_len(len - 1);- Some(ret) }+ Some(ret) } /// Retains only the elements specified by the predicate.@@ -2906,9 +2906,9 @@ impl<T, A: Allocator> Vec<T, A> { if self.len == 0 { None } else {+ self.len -= 1; // ignore-tidy-undocumented-unsafe unsafe {- self.len -= 1; core::hint::assert_unchecked(self.len < self.capacity()); Some(ptr::read(self.as_ptr().add(self.len()))) }@@ -4067,9 +4067,9 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> { /// ``` #[inline] fn into_iter(self) -> Self::IntoIter {+ let me = ManuallyDrop::new(self); // ignore-tidy-undocumented-unsafe unsafe {- let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); let buf = me.buf.non_null(); let begin = buf.as_ptr();@@ -4175,10 +4175,10 @@ impl<T, A: Allocator> Vec<T, A> { (low, high) ); self.reserve(additional);+ let ptr = self.as_mut_ptr();+ let mut local_len = SetLenOnDrop::new(&mut self.len); // ignore-tidy-undocumented-unsafe unsafe {- let ptr = self.as_mut_ptr();- let mut local_len = SetLenOnDrop::new(&mut self.len); iterator.for_each(move |element| { ptr::write(ptr.add(local_len.current_len()), element); // Since the loop executes user code which can panic we have to updatelibrary/alloc/src/vec/spec_from_iter.rs1 + / 1 −
@@ -46,9 +46,9 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> { // But it is a conservative choice. let has_advanced = iterator.buf != iterator.ptr; if !has_advanced || iterator.len() >= iterator.cap / 2 {+ let it = ManuallyDrop::new(iterator); // ignore-tidy-undocumented-unsafe unsafe {- let it = ManuallyDrop::new(iterator); if has_advanced { ptr::copy(it.ptr.as_ptr(), it.buf.as_ptr(), it.len()); }