Skip to content

Commit b6c9e44

Browse files
committed
add Box::as_ptr and Box::as_mut_ptr methods
1 parent fd2b339 commit b6c9e44

File tree

2 files changed

+90
-2
lines changed

2 files changed

+90
-2
lines changed

Diff for: alloc/src/boxed.rs

+89
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,95 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
12541254
unsafe { (Unique::from(&mut *ptr), alloc) }
12551255
}
12561256

1257+
/// Returns a raw mutable pointer to the `Box`'s contents.
1258+
///
1259+
/// The caller must ensure that the `Box` outlives the pointer this
1260+
/// function returns, or else it will end up dangling.
1261+
///
1262+
/// This method guarantees that for the purpose of the aliasing model, this method
1263+
/// does not materialize a reference to the underlying memory, and thus the returned pointer
1264+
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
1265+
/// Note that calling other methods that materialize references to the memory
1266+
/// may still invalidate this pointer.
1267+
/// See the example below for how this guarantee can be used.
1268+
///
1269+
/// # Examples
1270+
///
1271+
/// Due to the aliasing guarantee, the following code is legal:
1272+
///
1273+
/// ```rust
1274+
/// #![feature(box_as_ptr)]
1275+
///
1276+
/// unsafe {
1277+
/// let mut b = Box::new(0);
1278+
/// let ptr1 = Box::as_mut_ptr(&mut b);
1279+
/// ptr1.write(1);
1280+
/// let ptr2 = Box::as_mut_ptr(&mut b);
1281+
/// ptr2.write(2);
1282+
/// // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
1283+
/// ptr1.write(3);
1284+
/// }
1285+
/// ```
1286+
///
1287+
/// [`as_mut_ptr`]: Self::as_mut_ptr
1288+
/// [`as_ptr`]: Self::as_ptr
1289+
#[unstable(feature = "box_as_ptr", issue = "129090")]
1290+
#[rustc_never_returns_null_ptr]
1291+
#[inline]
1292+
pub fn as_mut_ptr(b: &mut Self) -> *mut T {
1293+
// This is a primitive deref, not going through `DerefMut`, and therefore not materializing
1294+
// any references.
1295+
ptr::addr_of_mut!(**b)
1296+
}
1297+
1298+
/// Returns a raw pointer to the `Box`'s contents.
1299+
///
1300+
/// The caller must ensure that the `Box` outlives the pointer this
1301+
/// function returns, or else it will end up dangling.
1302+
///
1303+
/// The caller must also ensure that the memory the pointer (non-transitively) points to
1304+
/// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer
1305+
/// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`].
1306+
///
1307+
/// This method guarantees that for the purpose of the aliasing model, this method
1308+
/// does not materialize a reference to the underlying memory, and thus the returned pointer
1309+
/// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
1310+
/// Note that calling other methods that materialize mutable references to the memory,
1311+
/// as well as writing to this memory, may still invalidate this pointer.
1312+
/// See the example below for how this guarantee can be used.
1313+
///
1314+
/// # Examples
1315+
///
1316+
/// Due to the aliasing guarantee, the following code is legal:
1317+
///
1318+
/// ```rust
1319+
/// #![feature(box_as_ptr)]
1320+
///
1321+
/// unsafe {
1322+
/// let mut v = Box::new(0);
1323+
/// let ptr1 = Box::as_ptr(&v);
1324+
/// let ptr2 = Box::as_mut_ptr(&mut v);
1325+
/// let _val = ptr2.read();
1326+
/// // No write to this memory has happened yet, so `ptr1` is still valid.
1327+
/// let _val = ptr1.read();
1328+
/// // However, once we do a write...
1329+
/// ptr2.write(1);
1330+
/// // ... `ptr1` is no longer valid.
1331+
/// // This would be UB: let _val = ptr1.read();
1332+
/// }
1333+
/// ```
1334+
///
1335+
/// [`as_mut_ptr`]: Self::as_mut_ptr
1336+
/// [`as_ptr`]: Self::as_ptr
1337+
#[unstable(feature = "box_as_ptr", issue = "129090")]
1338+
#[rustc_never_returns_null_ptr]
1339+
#[inline]
1340+
pub fn as_ptr(b: &Self) -> *const T {
1341+
// This is a primitive deref, not going through `DerefMut`, and therefore not materializing
1342+
// any references.
1343+
ptr::addr_of!(**b)
1344+
}
1345+
12571346
/// Returns a reference to the underlying allocator.
12581347
///
12591348
/// Note: this is an associated function, which means that you have

Diff for: alloc/src/vec/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ impl<T, A: Allocator> Vec<T, A> {
13341334
self.buf.ptr()
13351335
}
13361336

1337-
/// Returns an unsafe mutable pointer to the vector's buffer, or a dangling
1337+
/// Returns a raw mutable pointer to the vector's buffer, or a dangling
13381338
/// raw pointer valid for zero sized reads if the vector didn't allocate.
13391339
///
13401340
/// The caller must ensure that the vector outlives the pointer this
@@ -1350,7 +1350,6 @@ impl<T, A: Allocator> Vec<T, A> {
13501350
/// may still invalidate this pointer.
13511351
/// See the second example below for how this guarantee can be used.
13521352
///
1353-
///
13541353
/// # Examples
13551354
///
13561355
/// ```

0 commit comments

Comments
 (0)