Skip to content

Commit 1b7dec9

Browse files
committed
Auto merge of #71326 - Dylan-DPC:rollup-hdlkdj5, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #71107 (Address concerns of weak-into-raw) - #71188 (Fixed missing trait method suggests incorrect code (self parameter not named "self"). ) - #71300 (Clarify when to use the tracking issue template) - #71315 (Add example in the alternative in std::mem::transmute docs) - #71319 (Clean up E0522 explanation) Failed merges: r? @ghost
2 parents 36b1a92 + 1d2532b commit 1b7dec9

File tree

8 files changed

+138
-69
lines changed

8 files changed

+138
-69
lines changed

.github/ISSUE_TEMPLATE/tracking_issue.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: Tracking Issue
3-
about: A tracking issue for a feature in Rust.
3+
about: A tracking issue for an accepted feature or RFC in Rust.
44
title: Tracking Issue for XXX
55
labels: C-tracking-issue
66
---

src/liballoc/rc.rs

+40-27
Original file line numberDiff line numberDiff line change
@@ -569,9 +569,33 @@ impl<T: ?Sized> Rc<T> {
569569
/// ```
570570
#[stable(feature = "rc_raw", since = "1.17.0")]
571571
pub fn into_raw(this: Self) -> *const T {
572+
let ptr = Self::as_ptr(&this);
573+
mem::forget(this);
574+
ptr
575+
}
576+
577+
/// Provides a raw pointer to the data.
578+
///
579+
/// The counts are not affected in any way and the `Rc` is not consumed. The pointer is valid
580+
/// for as long there are strong counts in the `Rc`.
581+
///
582+
/// # Examples
583+
///
584+
/// ```
585+
/// #![feature(weak_into_raw)]
586+
///
587+
/// use std::rc::Rc;
588+
///
589+
/// let x = Rc::new("hello".to_owned());
590+
/// let y = Rc::clone(&x);
591+
/// let x_ptr = Rc::as_ptr(&x);
592+
/// assert_eq!(x_ptr, Rc::as_ptr(&y));
593+
/// assert_eq!(unsafe { &*x_ptr }, "hello");
594+
/// ```
595+
#[unstable(feature = "weak_into_raw", issue = "60728")]
596+
pub fn as_ptr(this: &Self) -> *const T {
572597
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
573598
let fake_ptr = ptr as *mut T;
574-
mem::forget(this);
575599

576600
// SAFETY: This cannot go through Deref::deref.
577601
// Instead, we manually offset the pointer rather than manifesting a reference.
@@ -1644,8 +1668,8 @@ impl<T> Weak<T> {
16441668

16451669
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
16461670
///
1647-
/// The pointer is valid only if there are some strong references. The pointer may be dangling
1648-
/// or even [`null`] otherwise.
1671+
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
1672+
/// unaligned or even [`null`] otherwise.
16491673
///
16501674
/// # Examples
16511675
///
@@ -1658,31 +1682,22 @@ impl<T> Weak<T> {
16581682
/// let strong = Rc::new("hello".to_owned());
16591683
/// let weak = Rc::downgrade(&strong);
16601684
/// // Both point to the same object
1661-
/// assert!(ptr::eq(&*strong, weak.as_raw()));
1685+
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
16621686
/// // The strong here keeps it alive, so we can still access the object.
1663-
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
1687+
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
16641688
///
16651689
/// drop(strong);
1666-
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
1690+
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
16671691
/// // undefined behaviour.
1668-
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
1692+
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
16691693
/// ```
16701694
///
16711695
/// [`null`]: ../../std/ptr/fn.null.html
16721696
#[unstable(feature = "weak_into_raw", issue = "60728")]
1673-
pub fn as_raw(&self) -> *const T {
1674-
match self.inner() {
1675-
None => ptr::null(),
1676-
Some(inner) => {
1677-
let offset = data_offset_sized::<T>();
1678-
let ptr = inner as *const RcBox<T>;
1679-
// Note: while the pointer we create may already point to dropped value, the
1680-
// allocation still lives (it must hold the weak point as long as we are alive).
1681-
// Therefore, the offset is OK to do, it won't get out of the allocation.
1682-
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1683-
ptr as *const T
1684-
}
1685-
}
1697+
pub fn as_ptr(&self) -> *const T {
1698+
let offset = data_offset_sized::<T>();
1699+
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1700+
ptr as *const T
16861701
}
16871702

16881703
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -1691,7 +1706,7 @@ impl<T> Weak<T> {
16911706
/// can be turned back into the `Weak<T>` with [`from_raw`].
16921707
///
16931708
/// The same restrictions of accessing the target of the pointer as with
1694-
/// [`as_raw`] apply.
1709+
/// [`as_ptr`] apply.
16951710
///
16961711
/// # Examples
16971712
///
@@ -1712,10 +1727,10 @@ impl<T> Weak<T> {
17121727
/// ```
17131728
///
17141729
/// [`from_raw`]: struct.Weak.html#method.from_raw
1715-
/// [`as_raw`]: struct.Weak.html#method.as_raw
1730+
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
17161731
#[unstable(feature = "weak_into_raw", issue = "60728")]
17171732
pub fn into_raw(self) -> *const T {
1718-
let result = self.as_raw();
1733+
let result = self.as_ptr();
17191734
mem::forget(self);
17201735
result
17211736
}
@@ -1730,9 +1745,8 @@ impl<T> Weak<T> {
17301745
///
17311746
/// # Safety
17321747
///
1733-
/// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was
1734-
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
1735-
/// count.
1748+
/// The pointer must have originated from the [`into_raw`] and must still own its potential
1749+
/// weak reference count.
17361750
///
17371751
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
17381752
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
@@ -1765,7 +1779,6 @@ impl<T> Weak<T> {
17651779
/// [`upgrade`]: struct.Weak.html#method.upgrade
17661780
/// [`Rc`]: struct.Rc.html
17671781
/// [`Weak`]: struct.Weak.html
1768-
/// [`as_raw`]: struct.Weak.html#method.as_raw
17691782
/// [`new`]: struct.Weak.html#method.new
17701783
/// [`forget`]: ../../std/mem/fn.forget.html
17711784
#[unstable(feature = "weak_into_raw", issue = "60728")]

src/liballoc/sync.rs

+40-27
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,33 @@ impl<T: ?Sized> Arc<T> {
566566
/// ```
567567
#[stable(feature = "rc_raw", since = "1.17.0")]
568568
pub fn into_raw(this: Self) -> *const T {
569+
let ptr = Self::as_ptr(&this);
570+
mem::forget(this);
571+
ptr
572+
}
573+
574+
/// Provides a raw pointer to the data.
575+
///
576+
/// The counts are not affected in way and the `Arc` is not consumed. The pointer is valid for
577+
/// as long as there are strong counts in the `Arc`.
578+
///
579+
/// # Examples
580+
///
581+
/// ```
582+
/// #![feature(weak_into_raw)]
583+
///
584+
/// use std::sync::Arc;
585+
///
586+
/// let x = Arc::new("hello".to_owned());
587+
/// let y = Arc::clone(&x);
588+
/// let x_ptr = Arc::as_ptr(&x);
589+
/// assert_eq!(x_ptr, Arc::as_ptr(&y));
590+
/// assert_eq!(unsafe { &*x_ptr }, "hello");
591+
/// ```
592+
#[unstable(feature = "weak_into_raw", issue = "60728")]
593+
pub fn as_ptr(this: &Self) -> *const T {
569594
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
570595
let fake_ptr = ptr as *mut T;
571-
mem::forget(this);
572596

573597
// SAFETY: This cannot go through Deref::deref.
574598
// Instead, we manually offset the pointer rather than manifesting a reference.
@@ -1340,8 +1364,8 @@ impl<T> Weak<T> {
13401364

13411365
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
13421366
///
1343-
/// The pointer is valid only if there are some strong references. The pointer may be dangling
1344-
/// or even [`null`] otherwise.
1367+
/// The pointer is valid only if there are some strong references. The pointer may be dangling,
1368+
/// unaligned or even [`null`] otherwise.
13451369
///
13461370
/// # Examples
13471371
///
@@ -1354,31 +1378,22 @@ impl<T> Weak<T> {
13541378
/// let strong = Arc::new("hello".to_owned());
13551379
/// let weak = Arc::downgrade(&strong);
13561380
/// // Both point to the same object
1357-
/// assert!(ptr::eq(&*strong, weak.as_raw()));
1381+
/// assert!(ptr::eq(&*strong, weak.as_ptr()));
13581382
/// // The strong here keeps it alive, so we can still access the object.
1359-
/// assert_eq!("hello", unsafe { &*weak.as_raw() });
1383+
/// assert_eq!("hello", unsafe { &*weak.as_ptr() });
13601384
///
13611385
/// drop(strong);
1362-
/// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to
1386+
/// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to
13631387
/// // undefined behaviour.
1364-
/// // assert_eq!("hello", unsafe { &*weak.as_raw() });
1388+
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
13651389
/// ```
13661390
///
13671391
/// [`null`]: ../../std/ptr/fn.null.html
13681392
#[unstable(feature = "weak_into_raw", issue = "60728")]
1369-
pub fn as_raw(&self) -> *const T {
1370-
match self.inner() {
1371-
None => ptr::null(),
1372-
Some(inner) => {
1373-
let offset = data_offset_sized::<T>();
1374-
let ptr = inner as *const ArcInner<T>;
1375-
// Note: while the pointer we create may already point to dropped value, the
1376-
// allocation still lives (it must hold the weak point as long as we are alive).
1377-
// Therefore, the offset is OK to do, it won't get out of the allocation.
1378-
let ptr = unsafe { (ptr as *const u8).offset(offset) };
1379-
ptr as *const T
1380-
}
1381-
}
1393+
pub fn as_ptr(&self) -> *const T {
1394+
let offset = data_offset_sized::<T>();
1395+
let ptr = self.ptr.cast::<u8>().as_ptr().wrapping_offset(offset);
1396+
ptr as *const T
13821397
}
13831398

13841399
/// Consumes the `Weak<T>` and turns it into a raw pointer.
@@ -1387,7 +1402,7 @@ impl<T> Weak<T> {
13871402
/// can be turned back into the `Weak<T>` with [`from_raw`].
13881403
///
13891404
/// The same restrictions of accessing the target of the pointer as with
1390-
/// [`as_raw`] apply.
1405+
/// [`as_ptr`] apply.
13911406
///
13921407
/// # Examples
13931408
///
@@ -1408,10 +1423,10 @@ impl<T> Weak<T> {
14081423
/// ```
14091424
///
14101425
/// [`from_raw`]: struct.Weak.html#method.from_raw
1411-
/// [`as_raw`]: struct.Weak.html#method.as_raw
1426+
/// [`as_ptr`]: struct.Weak.html#method.as_ptr
14121427
#[unstable(feature = "weak_into_raw", issue = "60728")]
14131428
pub fn into_raw(self) -> *const T {
1414-
let result = self.as_raw();
1429+
let result = self.as_ptr();
14151430
mem::forget(self);
14161431
result
14171432
}
@@ -1427,9 +1442,8 @@ impl<T> Weak<T> {
14271442
///
14281443
/// # Safety
14291444
///
1430-
/// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was
1431-
/// a corresponding [`forget`] on the `Weak<T>`) and must still own its potential weak reference
1432-
/// count.
1445+
/// The pointer must have originated from the [`into_raw`] and must still own its potential
1446+
/// weak reference count.
14331447
///
14341448
/// It is allowed for the strong count to be 0 at the time of calling this, but the weak count
14351449
/// must be non-zero or the pointer must have originated from a dangling `Weak<T>` (one created
@@ -1458,7 +1472,6 @@ impl<T> Weak<T> {
14581472
/// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none());
14591473
/// ```
14601474
///
1461-
/// [`as_raw`]: struct.Weak.html#method.as_raw
14621475
/// [`new`]: struct.Weak.html#method.new
14631476
/// [`into_raw`]: struct.Weak.html#method.into_raw
14641477
/// [`upgrade`]: struct.Weak.html#method.upgrade

src/libcore/intrinsics.rs

+18
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,24 @@ extern "rust-intrinsic" {
11001100
/// Below are common applications of `transmute` which can be replaced with safer
11011101
/// constructs.
11021102
///
1103+
/// Turning raw bytes(`&[u8]`) to `u32`, `f64`, etc.:
1104+
///
1105+
/// ```
1106+
/// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
1107+
///
1108+
/// let num = unsafe {
1109+
/// std::mem::transmute::<[u8; 4], u32>(raw_bytes);
1110+
/// };
1111+
///
1112+
/// // use `u32::from_ne_bytes` instead
1113+
/// let num = u32::from_ne_bytes(raw_bytes);
1114+
/// // or use `u32::from_le_bytes` or `u32::from_ge_bytes` to specify the endianness
1115+
/// let num = u32::from_le_bytes(raw_bytes);
1116+
/// assert_eq!(num, 0x12345678);
1117+
/// let num = u32::from_be_bytes(raw_bytes);
1118+
/// assert_eq!(num, 0x78563412);
1119+
/// ```
1120+
///
11031121
/// Turning a pointer into a `usize`:
11041122
///
11051123
/// ```
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
The lang attribute is intended for marking special items that are built-in to
2-
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect
3-
how the compiler behaves, as well as special functions that may be automatically
4-
invoked (such as the handler for out-of-bounds accesses when indexing a slice).
1+
The lang attribute was used in an invalid context.
2+
53
Erroneous code example:
64

75
```compile_fail,E0522
@@ -12,3 +10,8 @@ fn cookie() -> ! { // error: definition of an unknown language item: `cookie`
1210
loop {}
1311
}
1412
```
13+
14+
The lang attribute is intended for marking special items that are built-in to
15+
Rust itself. This includes special traits (like `Copy` and `Sized`) that affect
16+
how the compiler behaves, as well as special functions that may be automatically
17+
invoked (such as the handler for out-of-bounds accesses when indexing a slice).

src/librustc_typeck/check/mod.rs

+22-8
Original file line numberDiff line numberDiff line change
@@ -2251,26 +2251,39 @@ fn fn_sig_suggestion(
22512251
sig: &ty::FnSig<'_>,
22522252
ident: Ident,
22532253
predicates: ty::GenericPredicates<'_>,
2254+
assoc: &ty::AssocItem,
22542255
) -> String {
22552256
let args = sig
22562257
.inputs()
22572258
.iter()
2258-
.map(|ty| {
2259+
.enumerate()
2260+
.map(|(i, ty)| {
22592261
Some(match ty.kind {
2260-
ty::Param(param) if param.name == kw::SelfUpper => "self".to_string(),
2261-
ty::Ref(reg, ref_ty, mutability) => {
2262+
ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(),
2263+
ty::Ref(reg, ref_ty, mutability) if i == 0 => {
22622264
let reg = match &format!("{}", reg)[..] {
22632265
"'_" | "" => String::new(),
22642266
reg => format!("{} ", reg),
22652267
};
2266-
match ref_ty.kind {
2267-
ty::Param(param) if param.name == kw::SelfUpper => {
2268-
format!("&{}{}self", reg, mutability.prefix_str())
2268+
if assoc.fn_has_self_parameter {
2269+
match ref_ty.kind {
2270+
ty::Param(param) if param.name == kw::SelfUpper => {
2271+
format!("&{}{}self", reg, mutability.prefix_str())
2272+
}
2273+
2274+
_ => format!("self: {}", ty),
22692275
}
2270-
_ => format!("_: {:?}", ty),
2276+
} else {
2277+
format!("_: {:?}", ty)
2278+
}
2279+
}
2280+
_ => {
2281+
if assoc.fn_has_self_parameter && i == 0 {
2282+
format!("self: {:?}", ty)
2283+
} else {
2284+
format!("_: {:?}", ty)
22712285
}
22722286
}
2273-
_ => format!("_: {:?}", ty),
22742287
})
22752288
})
22762289
.chain(std::iter::once(if sig.c_variadic { Some("...".to_string()) } else { None }))
@@ -2309,6 +2322,7 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
23092322
tcx.fn_sig(assoc.def_id).skip_binder(),
23102323
assoc.ident,
23112324
tcx.predicates_of(assoc.def_id),
2325+
assoc,
23122326
)
23132327
}
23142328
ty::AssocKind::Type => format!("type {} = Type;", assoc.ident),

src/test/ui/missing/missing-items/auxiliary/m1.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ pub trait X {
22
const CONSTANT: u32;
33
type Type;
44
fn method(&self, s: String) -> Self::Type;
5+
fn method2(self: Box<Self>, s: String) -> Self::Type;
6+
fn method3(other: &Self, s: String) -> Self::Type;
7+
fn method4(&self, other: &Self) -> Self::Type;
8+
fn method5(self: &Box<Self>) -> Self::Type;
59
}

src/test/ui/missing/missing-items/m2.stderr

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`
1+
error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5`
22
--> $DIR/m2.rs:9:1
33
|
44
LL | impl m1::X for X {
5-
| ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method` in implementation
5+
| ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` in implementation
66
|
77
= help: implement the missing item: `const CONSTANT: u32 = 42;`
88
= help: implement the missing item: `type Type = Type;`
99
= help: implement the missing item: `fn method(&self, _: std::string::String) -> <Self as m1::X>::Type { todo!() }`
10+
= help: implement the missing item: `fn method2(self: std::boxed::Box<Self>, _: std::string::String) -> <Self as m1::X>::Type { todo!() }`
11+
= help: implement the missing item: `fn method3(_: &Self, _: std::string::String) -> <Self as m1::X>::Type { todo!() }`
12+
= help: implement the missing item: `fn method4(&self, _: &Self) -> <Self as m1::X>::Type { todo!() }`
13+
= help: implement the missing item: `fn method5(self: &std::boxed::Box<Self>) -> <Self as m1::X>::Type { todo!() }`
1014

1115
error: aborting due to previous error
1216

0 commit comments

Comments
 (0)