Skip to content

Commit 8197085

Browse files
committed
Auto merge of #61305 - Centril:rollup-t39m00m, r=Centril
Rollup of 11 pull requests Successful merges: - #58975 (Implement `iter::Sum` and `iter::Product` for `Option`) - #60542 (Add Step::sub_usize) - #60555 (Implement nth_back for RChunks(Exact)(Mut)) - #60766 (Weak::into_raw) - #61048 (Feature/nth back chunks) - #61191 (librustc_errors: Move annotation collection to own impl) - #61235 (Stabilize bufreader_buffer feature) - #61249 (Rename Place::local to Place::local_or_deref_local) - #61291 (Avoid unneeded bug!() call) - #61294 (Rename `TraitOrImpl` to `Assoc` and `trait_or_impl` to `assoc`.) - #61297 (Remove LLVM instruction stats and other (obsolete) codegen stats.) Failed merges: r? @ghost
2 parents 4b9d803 + 907f4fd commit 8197085

File tree

29 files changed

+900
-503
lines changed

29 files changed

+900
-503
lines changed

src/liballoc/rc.rs

+156-6
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ use core::fmt;
239239
use core::hash::{Hash, Hasher};
240240
use core::intrinsics::abort;
241241
use core::marker::{self, Unpin, Unsize, PhantomData};
242-
use core::mem::{self, align_of_val, forget, size_of_val};
242+
use core::mem::{self, align_of, align_of_val, forget, size_of_val};
243243
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
244244
use core::pin::Pin;
245245
use core::ptr::{self, NonNull};
@@ -416,11 +416,7 @@ impl<T: ?Sized> Rc<T> {
416416
/// ```
417417
#[stable(feature = "rc_raw", since = "1.17.0")]
418418
pub unsafe fn from_raw(ptr: *const T) -> Self {
419-
// Align the unsized value to the end of the RcBox.
420-
// Because it is ?Sized, it will always be the last field in memory.
421-
let align = align_of_val(&*ptr);
422-
let layout = Layout::new::<RcBox<()>>();
423-
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
419+
let offset = data_offset(ptr);
424420

425421
// Reverse the offset to find the original RcBox.
426422
let fake_ptr = ptr as *mut RcBox<T>;
@@ -1262,6 +1258,143 @@ impl<T> Weak<T> {
12621258
ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
12631259
}
12641260
}
1261+
1262+
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
1263+
///
1264+
/// It is up to the caller to ensure that the object is still alive when accessing it through
1265+
/// the pointer.
1266+
///
1267+
/// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
1268+
///
1269+
/// # Examples
1270+
///
1271+
/// ```
1272+
/// #![feature(weak_into_raw)]
1273+
///
1274+
/// use std::rc::{Rc, Weak};
1275+
/// use std::ptr;
1276+
///
1277+
/// let strong = Rc::new(42);
1278+
/// let weak = Rc::downgrade(&strong);
1279+
/// // Both point to the same object
1280+
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
1281+
/// // The strong here keeps it alive, so we can still access the object.
1282+
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1283+
///
1284+
/// drop(strong);
1285+
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
1286+
/// // undefined behaviour.
1287+
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1288+
/// ```
1289+
///
1290+
/// [`null`]: ../../std/ptr/fn.null.html
1291+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1292+
pub fn as_raw(this: &Self) -> *const T {
1293+
match this.inner() {
1294+
None => ptr::null(),
1295+
Some(inner) => {
1296+
let offset = data_offset_sized::<T>();
1297+
let ptr = inner as *const RcBox<T>;
1298+
// Note: while the pointer we create may already point to dropped value, the
1299+
// allocation still lives (it must hold the weak point as long as we are alive).
1300+
// Therefore, the offset is OK to do, it won't get out of the allocation.
1301+
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1302+
ptr as *const T
1303+
}
1304+
}
1305+
}
1306+
1307+
/// Consumes the `Weak<T>` and turns it into a raw pointer.
1308+
///
1309+
/// This converts the weak pointer into a raw pointer, preserving the original weak count. It
1310+
/// can be turned back into the `Weak<T>` with [`from_raw`].
1311+
///
1312+
/// The same restrictions of accessing the target of the pointer as with
1313+
/// [`as_raw`] apply.
1314+
///
1315+
/// # Examples
1316+
///
1317+
/// ```
1318+
/// #![feature(weak_into_raw)]
1319+
///
1320+
/// use std::rc::{Rc, Weak};
1321+
///
1322+
/// let strong = Rc::new(42);
1323+
/// let weak = Rc::downgrade(&strong);
1324+
/// let raw = Weak::into_raw(weak);
1325+
///
1326+
/// assert_eq!(1, Rc::weak_count(&strong));
1327+
/// assert_eq!(42, unsafe { *raw });
1328+
///
1329+
/// drop(unsafe { Weak::from_raw(raw) });
1330+
/// assert_eq!(0, Rc::weak_count(&strong));
1331+
/// ```
1332+
///
1333+
/// [`from_raw`]: struct.Weak.html#method.from_raw
1334+
/// [`as_raw`]: struct.Weak.html#method.as_raw
1335+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1336+
pub fn into_raw(this: Self) -> *const T {
1337+
let result = Self::as_raw(&this);
1338+
mem::forget(this);
1339+
result
1340+
}
1341+
1342+
/// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>`.
1343+
///
1344+
/// This can be used to safely get a strong reference (by calling [`upgrade`]
1345+
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
1346+
///
1347+
/// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
1348+
/// returned.
1349+
///
1350+
/// # Safety
1351+
///
1352+
/// The pointer must represent one valid weak count. In other words, it must point to `T` which
1353+
/// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
1354+
/// 0. It is allowed for the strong count to be 0.
1355+
///
1356+
/// # Examples
1357+
///
1358+
/// ```
1359+
/// #![feature(weak_into_raw)]
1360+
///
1361+
/// use std::rc::{Rc, Weak};
1362+
///
1363+
/// let strong = Rc::new(42);
1364+
///
1365+
/// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
1366+
/// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
1367+
///
1368+
/// assert_eq!(2, Rc::weak_count(&strong));
1369+
///
1370+
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
1371+
/// assert_eq!(1, Rc::weak_count(&strong));
1372+
///
1373+
/// drop(strong);
1374+
///
1375+
/// // Decrement the last weak count.
1376+
/// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
1377+
/// ```
1378+
///
1379+
/// [`null`]: ../../std/ptr/fn.null.html
1380+
/// [`into_raw`]: struct.Weak.html#method.into_raw
1381+
/// [`upgrade`]: struct.Weak.html#method.upgrade
1382+
/// [`Rc`]: struct.Rc.html
1383+
/// [`Weak`]: struct.Weak.html
1384+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1385+
pub unsafe fn from_raw(ptr: *const T) -> Self {
1386+
if ptr.is_null() {
1387+
Self::new()
1388+
} else {
1389+
// See Rc::from_raw for details
1390+
let offset = data_offset(ptr);
1391+
let fake_ptr = ptr as *mut RcBox<T>;
1392+
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
1393+
Weak {
1394+
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
1395+
}
1396+
}
1397+
}
12651398
}
12661399

12671400
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
@@ -2007,3 +2140,20 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
20072140

20082141
#[stable(feature = "pin", since = "1.33.0")]
20092142
impl<T: ?Sized> Unpin for Rc<T> { }
2143+
2144+
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
2145+
// Align the unsized value to the end of the RcBox.
2146+
// Because it is ?Sized, it will always be the last field in memory.
2147+
let align = align_of_val(&*ptr);
2148+
let layout = Layout::new::<RcBox<()>>();
2149+
(layout.size() + layout.padding_needed_for(align)) as isize
2150+
}
2151+
2152+
/// Computes the offset of the data field within ArcInner.
2153+
///
2154+
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2155+
fn data_offset_sized<T>() -> isize {
2156+
let align = align_of::<T>();
2157+
let layout = Layout::new::<RcBox<()>>();
2158+
(layout.size() + layout.padding_needed_for(align)) as isize
2159+
}

src/liballoc/sync.rs

+158-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::borrow;
1313
use core::fmt;
1414
use core::cmp::{self, Ordering};
1515
use core::intrinsics::abort;
16-
use core::mem::{self, align_of_val, size_of_val};
16+
use core::mem::{self, align_of, align_of_val, size_of_val};
1717
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
1818
use core::pin::Pin;
1919
use core::ptr::{self, NonNull};
@@ -397,11 +397,7 @@ impl<T: ?Sized> Arc<T> {
397397
/// ```
398398
#[stable(feature = "rc_raw", since = "1.17.0")]
399399
pub unsafe fn from_raw(ptr: *const T) -> Self {
400-
// Align the unsized value to the end of the ArcInner.
401-
// Because it is ?Sized, it will always be the last field in memory.
402-
let align = align_of_val(&*ptr);
403-
let layout = Layout::new::<ArcInner<()>>();
404-
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
400+
let offset = data_offset(ptr);
405401

406402
// Reverse the offset to find the original ArcInner.
407403
let fake_ptr = ptr as *mut ArcInner<T>;
@@ -1071,6 +1067,144 @@ impl<T> Weak<T> {
10711067
ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
10721068
}
10731069
}
1070+
1071+
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
1072+
///
1073+
/// It is up to the caller to ensure that the object is still alive when accessing it through
1074+
/// the pointer.
1075+
///
1076+
/// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
1077+
///
1078+
/// # Examples
1079+
///
1080+
/// ```
1081+
/// #![feature(weak_into_raw)]
1082+
///
1083+
/// use std::sync::{Arc, Weak};
1084+
/// use std::ptr;
1085+
///
1086+
/// let strong = Arc::new(42);
1087+
/// let weak = Arc::downgrade(&strong);
1088+
/// // Both point to the same object
1089+
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
1090+
/// // The strong here keeps it alive, so we can still access the object.
1091+
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1092+
///
1093+
/// drop(strong);
1094+
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
1095+
/// // undefined behaviour.
1096+
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
1097+
/// ```
1098+
///
1099+
/// [`null`]: ../../std/ptr/fn.null.html
1100+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1101+
pub fn as_raw(this: &Self) -> *const T {
1102+
match this.inner() {
1103+
None => ptr::null(),
1104+
Some(inner) => {
1105+
let offset = data_offset_sized::<T>();
1106+
let ptr = inner as *const ArcInner<T>;
1107+
// Note: while the pointer we create may already point to dropped value, the
1108+
// allocation still lives (it must hold the weak point as long as we are alive).
1109+
// Therefore, the offset is OK to do, it won't get out of the allocation.
1110+
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1111+
ptr as *const T
1112+
}
1113+
}
1114+
}
1115+
1116+
/// Consumes the `Weak<T>` and turns it into a raw pointer.
1117+
///
1118+
/// This converts the weak pointer into a raw pointer, preserving the original weak count. It
1119+
/// can be turned back into the `Weak<T>` with [`from_raw`].
1120+
///
1121+
/// The same restrictions of accessing the target of the pointer as with
1122+
/// [`as_raw`] apply.
1123+
///
1124+
/// # Examples
1125+
///
1126+
/// ```
1127+
/// #![feature(weak_into_raw)]
1128+
///
1129+
/// use std::sync::{Arc, Weak};
1130+
///
1131+
/// let strong = Arc::new(42);
1132+
/// let weak = Arc::downgrade(&strong);
1133+
/// let raw = Weak::into_raw(weak);
1134+
///
1135+
/// assert_eq!(1, Arc::weak_count(&strong));
1136+
/// assert_eq!(42, unsafe { *raw });
1137+
///
1138+
/// drop(unsafe { Weak::from_raw(raw) });
1139+
/// assert_eq!(0, Arc::weak_count(&strong));
1140+
/// ```
1141+
///
1142+
/// [`from_raw`]: struct.Weak.html#method.from_raw
1143+
/// [`as_raw`]: struct.Weak.html#method.as_raw
1144+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1145+
pub fn into_raw(this: Self) -> *const T {
1146+
let result = Self::as_raw(&this);
1147+
mem::forget(this);
1148+
result
1149+
}
1150+
1151+
/// Converts a raw pointer previously created by [`into_raw`] back into
1152+
/// `Weak<T>`.
1153+
///
1154+
/// This can be used to safely get a strong reference (by calling [`upgrade`]
1155+
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
1156+
///
1157+
/// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
1158+
/// returned.
1159+
///
1160+
/// # Safety
1161+
///
1162+
/// The pointer must represent one valid weak count. In other words, it must point to `T` which
1163+
/// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
1164+
/// 0. It is allowed for the strong count to be 0.
1165+
///
1166+
/// # Examples
1167+
///
1168+
/// ```
1169+
/// #![feature(weak_into_raw)]
1170+
///
1171+
/// use std::sync::{Arc, Weak};
1172+
///
1173+
/// let strong = Arc::new(42);
1174+
///
1175+
/// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
1176+
/// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
1177+
///
1178+
/// assert_eq!(2, Arc::weak_count(&strong));
1179+
///
1180+
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
1181+
/// assert_eq!(1, Arc::weak_count(&strong));
1182+
///
1183+
/// drop(strong);
1184+
///
1185+
/// // Decrement the last weak count.
1186+
/// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
1187+
/// ```
1188+
///
1189+
/// [`null`]: ../../std/ptr/fn.null.html
1190+
/// [`into_raw`]: struct.Weak.html#method.into_raw
1191+
/// [`upgrade`]: struct.Weak.html#method.upgrade
1192+
/// [`Weak`]: struct.Weak.html
1193+
/// [`Arc`]: struct.Arc.html
1194+
#[unstable(feature = "weak_into_raw", issue = "60728")]
1195+
pub unsafe fn from_raw(ptr: *const T) -> Self {
1196+
if ptr.is_null() {
1197+
Self::new()
1198+
} else {
1199+
// See Arc::from_raw for details
1200+
let offset = data_offset(ptr);
1201+
let fake_ptr = ptr as *mut ArcInner<T>;
1202+
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
1203+
Weak {
1204+
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
1205+
}
1206+
}
1207+
}
10741208
}
10751209

10761210
impl<T: ?Sized> Weak<T> {
@@ -2150,3 +2284,21 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
21502284

21512285
#[stable(feature = "pin", since = "1.33.0")]
21522286
impl<T: ?Sized> Unpin for Arc<T> { }
2287+
2288+
/// Computes the offset of the data field within ArcInner.
2289+
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
2290+
// Align the unsized value to the end of the ArcInner.
2291+
// Because it is ?Sized, it will always be the last field in memory.
2292+
let align = align_of_val(&*ptr);
2293+
let layout = Layout::new::<ArcInner<()>>();
2294+
(layout.size() + layout.padding_needed_for(align)) as isize
2295+
}
2296+
2297+
/// Computes the offset of the data field within ArcInner.
2298+
///
2299+
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
2300+
fn data_offset_sized<T>() -> isize {
2301+
let align = align_of::<T>();
2302+
let layout = Layout::new::<ArcInner<()>>();
2303+
(layout.size() + layout.padding_needed_for(align)) as isize
2304+
}

0 commit comments

Comments
 (0)