Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
#![feature(fundamental)]
#![feature(internal_uninit_const)]
#![feature(lang_items)]
#![feature(layout_for_ptr)]
#![feature(libc)]
#![feature(negative_impls)]
#![feature(new_uninit)]
Expand All @@ -109,6 +110,7 @@
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(ptr_offset_from)]
#![feature(raw_ref_op)]
#![feature(rustc_attrs)]
#![feature(receiver_trait)]
#![feature(min_specialization)]
Expand Down
32 changes: 15 additions & 17 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
use core::iter;
use core::marker::{self, PhantomData, Unpin, Unsize};
use core::mem::{self, align_of, align_of_val, forget, size_of_val};
use core::mem::{self, align_of_val_raw, forget, size_of_val};
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
use core::pin::Pin;
use core::ptr::{self, NonNull};
Expand Down Expand Up @@ -591,17 +591,13 @@ impl<T: ?Sized> Rc<T> {
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(this: &Self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
let fake_ptr = ptr as *mut T;

// SAFETY: This cannot go through Deref::deref.
// Instead, we manually offset the pointer rather than manifesting a reference.
// This is so that the returned pointer retains the same provenance as our pointer.
// This is required so that e.g. `get_mut` can write through the pointer
// after the Rc is recovered through `from_raw`.
unsafe {
let offset = data_offset(&(*ptr).value);
set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
}
unsafe { &raw const (*ptr).value }
}

/// Constructs an `Rc<T>` from a raw pointer.
Expand Down Expand Up @@ -1708,9 +1704,18 @@ impl<T> Weak<T> {
/// [`null`]: ../../std/ptr/fn.null.html
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let offset = data_offset_sized::<T>();
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
ptr as *const T
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
let fake_ptr = ptr as *mut T;

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX). data_offset is safe to call, because we
// know a pointer to unsized T must be derived from a real unsized T,
// because dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for dangling weak refs.
unsafe {
let offset = data_offset(&raw const (*ptr).value);
set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset))
}
}

/// Consumes the `Weak<T>` and turns it into a raw pointer.
Expand Down Expand Up @@ -2118,14 +2123,7 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
// Because it is ?Sized, it will always be the last field in memory.
// Note: This is a detail of the current implementation of the compiler,
// and is not a guaranteed language detail. Do not rely on it outside of std.
unsafe { data_offset_align(align_of_val(&*ptr)) }
}

/// Computes the offset of the data field within `RcBox`.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
data_offset_align(align_of::<T>())
unsafe { data_offset_align(align_of_val_raw(ptr)) }
}

#[inline]
Expand Down
30 changes: 14 additions & 16 deletions src/liballoc/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use core::hash::{Hash, Hasher};
use core::intrinsics::abort;
use core::iter;
use core::marker::{PhantomData, Unpin, Unsize};
use core::mem::{self, align_of, align_of_val, size_of_val};
use core::mem::{self, align_of_val, size_of_val};
use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver};
use core::pin::Pin;
use core::ptr::{self, NonNull};
Expand Down Expand Up @@ -590,17 +590,13 @@ impl<T: ?Sized> Arc<T> {
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(this: &Self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
let fake_ptr = ptr as *mut T;

// SAFETY: This cannot go through Deref::deref.
// Instead, we manually offset the pointer rather than manifesting a reference.
// This is so that the returned pointer retains the same provenance as our pointer.
// This is required so that e.g. `get_mut` can write through the pointer
// after the Arc is recovered through `from_raw`.
unsafe {
let offset = data_offset(&(*ptr).data);
set_data_ptr(fake_ptr, (ptr as *mut u8).offset(offset))
}
unsafe { &raw const (*ptr).data }
}

/// Constructs an `Arc<T>` from a raw pointer.
Expand Down Expand Up @@ -1476,9 +1472,18 @@ impl<T> Weak<T> {
/// [`null`]: ../../std/ptr/fn.null.html
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let offset = data_offset_sized::<T>();
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
ptr as *const T
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
let fake_ptr = ptr as *mut T;

// SAFETY: we must offset the pointer manually, and said pointer may be
// a dangling weak (usize::MAX). data_offset is safe to call, because we
// know a pointer to unsized T must be derived from a real unsized T,
// because dangling weaks are only created for sized T. wrapping_offset
// is used so that we can use the same code path for dangling weak refs.
unsafe {
let offset = data_offset(&raw const (*ptr).data);
set_data_ptr(fake_ptr, (ptr as *mut u8).wrapping_offset(offset))
}
}

/// Consumes the `Weak<T>` and turns it into a raw pointer.
Expand Down Expand Up @@ -2279,13 +2284,6 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
unsafe { data_offset_align(align_of_val(&*ptr)) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops this line should have been align_of_val_raw now, right?

But I doubt that that's enough to fix #80365.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it definitely should have been. I don't know how I missed this one 🙃

}

/// Computes the offset of the data field within `ArcInner`.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
data_offset_align(align_of::<T>())
}

#[inline]
fn data_offset_align(align: usize) -> isize {
let layout = Layout::new::<ArcInner<()>>();
Expand Down