Skip to content

Commit

Permalink
Auto merge of rust-lang#125313 - matthiaskrgr:rollup-65etxv0, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#125034 (Weekly `cargo update`)
 - rust-lang#125093 (Add `fn into_raw_with_allocator` to Rc/Arc/Weak.)
 - rust-lang#125282 (Never type unsafe lint improvements)
 - rust-lang#125301 (fix suggestion in E0373 for !Unpin coroutines)
 - rust-lang#125302 (defrost `RUST_MIN_STACK=ice rustc hello.rs`)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed May 20, 2024
2 parents 529d2f2 + d65aacc commit ae94e59
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 10 deletions.
50 changes: 40 additions & 10 deletions alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,33 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
ptr
}

/// Consumes the `Rc`, returning the wrapped pointer and allocator.
///
/// To avoid a memory leak the pointer must be converted back to an `Rc` using
/// [`Rc::from_raw_in`].
///
/// # Examples
///
/// ```
/// #![feature(allocator_api)]
/// use std::rc::Rc;
/// use std::alloc::System;
///
/// let x = Rc::new_in("hello".to_owned(), System);
/// let (ptr, alloc) = Rc::into_raw_with_allocator(x);
/// assert_eq!(unsafe { &*ptr }, "hello");
/// let x = unsafe { Rc::from_raw_in(ptr, alloc) };
/// assert_eq!(&*x, "hello");
/// ```
#[unstable(feature = "allocator_api", issue = "32838")]
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
let alloc = unsafe { ptr::read(&this.alloc) };
(ptr, alloc)
}

/// Provides a raw pointer to the data.
///
/// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid
Expand Down Expand Up @@ -3024,39 +3051,42 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
result
}

/// Consumes the `Weak<T>` and turns it into a raw pointer.
/// Consumes the `Weak<T>`, returning the wrapped pointer and allocator.
///
/// This converts the weak pointer into a raw pointer, while still preserving the ownership of
/// one weak reference (the weak count is not modified by this operation). It can be turned
/// back into the `Weak<T>` with [`from_raw`].
/// back into the `Weak<T>` with [`from_raw_in`].
///
/// The same restrictions of accessing the target of the pointer as with
/// [`as_ptr`] apply.
///
/// # Examples
///
/// ```
/// #![feature(allocator_api)]
/// use std::rc::{Rc, Weak};
/// use std::alloc::System;
///
/// let strong = Rc::new("hello".to_owned());
/// let strong = Rc::new_in("hello".to_owned(), System);
/// let weak = Rc::downgrade(&strong);
/// let raw = weak.into_raw();
/// let (raw, alloc) = weak.into_raw_with_allocator();
///
/// assert_eq!(1, Rc::weak_count(&strong));
/// assert_eq!("hello", unsafe { &*raw });
///
/// drop(unsafe { Weak::from_raw(raw) });
/// drop(unsafe { Weak::from_raw_in(raw, alloc) });
/// assert_eq!(0, Rc::weak_count(&strong));
/// ```
///
/// [`from_raw`]: Weak::from_raw
/// [`from_raw_in`]: Weak::from_raw_in
/// [`as_ptr`]: Weak::as_ptr
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn into_raw_and_alloc(self) -> (*const T, A) {
let rc = mem::ManuallyDrop::new(self);
let result = rc.as_ptr();
let alloc = unsafe { ptr::read(&rc.alloc) };
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
let alloc = unsafe { ptr::read(&this.alloc) };
(result, alloc)
}

Expand Down
67 changes: 67 additions & 0 deletions alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,34 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
ptr
}

/// Consumes the `Arc`, returning the wrapped pointer and allocator.
///
/// To avoid a memory leak the pointer must be converted back to an `Arc` using
/// [`Arc::from_raw_in`].
///
/// # Examples
///
/// ```
/// #![feature(allocator_api)]
/// use std::sync::Arc;
/// use std::alloc::System;
///
/// let x = Arc::new_in("hello".to_owned(), System);
/// let (ptr, alloc) = Arc::into_raw_with_allocator(x);
/// assert_eq!(unsafe { &*ptr }, "hello");
/// let x = unsafe { Arc::from_raw_in(ptr, alloc) };
/// assert_eq!(&*x, "hello");
/// ```
#[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
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
let alloc = unsafe { ptr::read(&this.alloc) };
(ptr, alloc)
}

/// Provides a raw pointer to the data.
///
/// The counts are not affected in any way and the `Arc` is not consumed. The pointer is valid for
Expand Down Expand Up @@ -2740,6 +2768,45 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
result
}

/// Consumes the `Weak<T>`, returning the wrapped pointer and allocator.
///
/// This converts the weak pointer into a raw pointer, while still preserving the ownership of
/// one weak reference (the weak count is not modified by this operation). It can be turned
/// back into the `Weak<T>` with [`from_raw_in`].
///
/// The same restrictions of accessing the target of the pointer as with
/// [`as_ptr`] apply.
///
/// # Examples
///
/// ```
/// #![feature(allocator_api)]
/// use std::sync::{Arc, Weak};
/// use std::alloc::System;
///
/// let strong = Arc::new_in("hello".to_owned(), System);
/// let weak = Arc::downgrade(&strong);
/// let (raw, alloc) = weak.into_raw_with_allocator();
///
/// assert_eq!(1, Arc::weak_count(&strong));
/// assert_eq!("hello", unsafe { &*raw });
///
/// drop(unsafe { Weak::from_raw_in(raw, alloc) });
/// assert_eq!(0, Arc::weak_count(&strong));
/// ```
///
/// [`from_raw_in`]: Weak::from_raw_in
/// [`as_ptr`]: Weak::as_ptr
#[must_use = "losing the pointer will leak memory"]
#[unstable(feature = "allocator_api", issue = "32838")]
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
let alloc = unsafe { ptr::read(&this.alloc) };
(result, alloc)
}

/// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>` in the provided
/// allocator.
///
Expand Down

0 comments on commit ae94e59

Please sign in to comment.