diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 9457cce11afbe..51bf0c3ee6736 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -1,6 +1,6 @@ --- name: Tracking Issue -about: A tracking issue for a feature in Rust. +about: A tracking issue for an accepted feature or RFC in Rust. title: Tracking Issue for XXX labels: C-tracking-issue --- diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index abc4056cf5695..e106b4354e4e9 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -569,9 +569,33 @@ impl Rc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { + let ptr = Self::as_ptr(&this); + mem::forget(this); + ptr + } + + /// 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 + /// for as long there are strong counts in the `Rc`. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::rc::Rc; + /// + /// let x = Rc::new("hello".to_owned()); + /// let y = Rc::clone(&x); + /// let x_ptr = Rc::as_ptr(&x); + /// assert_eq!(x_ptr, Rc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut RcBox = NonNull::as_ptr(this.ptr); let fake_ptr = ptr as *mut T; - mem::forget(this); // SAFETY: This cannot go through Deref::deref. // Instead, we manually offset the pointer rather than manifesting a reference. @@ -1644,8 +1668,8 @@ impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// - /// The pointer is valid only if there are some strong references. The pointer may be dangling - /// or even [`null`] otherwise. + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. /// /// # Examples /// @@ -1658,31 +1682,22 @@ impl Weak { /// let strong = Rc::new("hello".to_owned()); /// let weak = Rc::downgrade(&strong); /// // Both point to the same object - /// assert!(ptr::eq(&*strong, weak.as_raw())); + /// assert!(ptr::eq(&*strong, weak.as_ptr())); /// // The strong here keeps it alive, so we can still access the object. - /// assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// /// drop(strong); - /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to /// // undefined behaviour. - /// // assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// ``` /// /// [`null`]: ../../std/ptr/fn.null.html #[unstable(feature = "weak_into_raw", issue = "60728")] - pub fn as_raw(&self) -> *const T { - match self.inner() { - None => ptr::null(), - Some(inner) => { - let offset = data_offset_sized::(); - let ptr = inner as *const RcBox; - // Note: while the pointer we create may already point to dropped value, the - // allocation still lives (it must hold the weak point as long as we are alive). - // Therefore, the offset is OK to do, it won't get out of the allocation. - let ptr = unsafe { (ptr as *const u8).offset(offset) }; - ptr as *const T - } - } + pub fn as_ptr(&self) -> *const T { + let offset = data_offset_sized::(); + let ptr = self.ptr.cast::().as_ptr().wrapping_offset(offset); + ptr as *const T } /// Consumes the `Weak` and turns it into a raw pointer. @@ -1691,7 +1706,7 @@ impl Weak { /// can be turned back into the `Weak` with [`from_raw`]. /// /// The same restrictions of accessing the target of the pointer as with - /// [`as_raw`] apply. + /// [`as_ptr`] apply. /// /// # Examples /// @@ -1712,10 +1727,10 @@ impl Weak { /// ``` /// /// [`from_raw`]: struct.Weak.html#method.from_raw - /// [`as_raw`]: struct.Weak.html#method.as_raw + /// [`as_ptr`]: struct.Weak.html#method.as_ptr #[unstable(feature = "weak_into_raw", issue = "60728")] pub fn into_raw(self) -> *const T { - let result = self.as_raw(); + let result = self.as_ptr(); mem::forget(self); result } @@ -1730,9 +1745,8 @@ impl Weak { /// /// # Safety /// - /// The pointer must have originated from the [`into_raw`] (or [`as_raw`], provided there was - /// a corresponding [`forget`] on the `Weak`) and must still own its potential weak reference - /// count. + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference count. /// /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count /// must be non-zero or the pointer must have originated from a dangling `Weak` (one created @@ -1765,7 +1779,6 @@ impl Weak { /// [`upgrade`]: struct.Weak.html#method.upgrade /// [`Rc`]: struct.Rc.html /// [`Weak`]: struct.Weak.html - /// [`as_raw`]: struct.Weak.html#method.as_raw /// [`new`]: struct.Weak.html#method.new /// [`forget`]: ../../std/mem/fn.forget.html #[unstable(feature = "weak_into_raw", issue = "60728")] diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index b1b22e46a7c2f..54df2b6085780 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -566,9 +566,33 @@ impl Arc { /// ``` #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { + let ptr = Self::as_ptr(&this); + mem::forget(this); + ptr + } + + /// Provides a raw pointer to the data. + /// + /// The counts are not affected in way and the `Arc` is not consumed. The pointer is valid for + /// as long as there are strong counts in the `Arc`. + /// + /// # Examples + /// + /// ``` + /// #![feature(weak_into_raw)] + /// + /// use std::sync::Arc; + /// + /// let x = Arc::new("hello".to_owned()); + /// let y = Arc::clone(&x); + /// let x_ptr = Arc::as_ptr(&x); + /// assert_eq!(x_ptr, Arc::as_ptr(&y)); + /// assert_eq!(unsafe { &*x_ptr }, "hello"); + /// ``` + #[unstable(feature = "weak_into_raw", issue = "60728")] + pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); let fake_ptr = ptr as *mut T; - mem::forget(this); // SAFETY: This cannot go through Deref::deref. // Instead, we manually offset the pointer rather than manifesting a reference. @@ -1340,8 +1364,8 @@ impl Weak { /// Returns a raw pointer to the object `T` pointed to by this `Weak`. /// - /// The pointer is valid only if there are some strong references. The pointer may be dangling - /// or even [`null`] otherwise. + /// The pointer is valid only if there are some strong references. The pointer may be dangling, + /// unaligned or even [`null`] otherwise. /// /// # Examples /// @@ -1354,31 +1378,22 @@ impl Weak { /// let strong = Arc::new("hello".to_owned()); /// let weak = Arc::downgrade(&strong); /// // Both point to the same object - /// assert!(ptr::eq(&*strong, weak.as_raw())); + /// assert!(ptr::eq(&*strong, weak.as_ptr())); /// // The strong here keeps it alive, so we can still access the object. - /// assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// /// drop(strong); - /// // But not any more. We can do weak.as_raw(), but accessing the pointer would lead to + /// // But not any more. We can do weak.as_ptr(), but accessing the pointer would lead to /// // undefined behaviour. - /// // assert_eq!("hello", unsafe { &*weak.as_raw() }); + /// // assert_eq!("hello", unsafe { &*weak.as_ptr() }); /// ``` /// /// [`null`]: ../../std/ptr/fn.null.html #[unstable(feature = "weak_into_raw", issue = "60728")] - pub fn as_raw(&self) -> *const T { - match self.inner() { - None => ptr::null(), - Some(inner) => { - let offset = data_offset_sized::(); - let ptr = inner as *const ArcInner; - // Note: while the pointer we create may already point to dropped value, the - // allocation still lives (it must hold the weak point as long as we are alive). - // Therefore, the offset is OK to do, it won't get out of the allocation. - let ptr = unsafe { (ptr as *const u8).offset(offset) }; - ptr as *const T - } - } + pub fn as_ptr(&self) -> *const T { + let offset = data_offset_sized::(); + let ptr = self.ptr.cast::().as_ptr().wrapping_offset(offset); + ptr as *const T } /// Consumes the `Weak` and turns it into a raw pointer. @@ -1387,7 +1402,7 @@ impl Weak { /// can be turned back into the `Weak` with [`from_raw`]. /// /// The same restrictions of accessing the target of the pointer as with - /// [`as_raw`] apply. + /// [`as_ptr`] apply. /// /// # Examples /// @@ -1408,10 +1423,10 @@ impl Weak { /// ``` /// /// [`from_raw`]: struct.Weak.html#method.from_raw - /// [`as_raw`]: struct.Weak.html#method.as_raw + /// [`as_ptr`]: struct.Weak.html#method.as_ptr #[unstable(feature = "weak_into_raw", issue = "60728")] pub fn into_raw(self) -> *const T { - let result = self.as_raw(); + let result = self.as_ptr(); mem::forget(self); result } @@ -1427,9 +1442,8 @@ impl Weak { /// /// # Safety /// - /// The pointer must have originated from the [`into_raw`] (or [`as_raw'], provided there was - /// a corresponding [`forget`] on the `Weak`) and must still own its potential weak reference - /// count. + /// The pointer must have originated from the [`into_raw`] and must still own its potential + /// weak reference count. /// /// It is allowed for the strong count to be 0 at the time of calling this, but the weak count /// must be non-zero or the pointer must have originated from a dangling `Weak` (one created @@ -1458,7 +1472,6 @@ impl Weak { /// assert!(unsafe { Weak::from_raw(raw_2) }.upgrade().is_none()); /// ``` /// - /// [`as_raw`]: struct.Weak.html#method.as_raw /// [`new`]: struct.Weak.html#method.new /// [`into_raw`]: struct.Weak.html#method.into_raw /// [`upgrade`]: struct.Weak.html#method.upgrade diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 4a11fb393899f..75c7313089112 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1100,6 +1100,24 @@ extern "rust-intrinsic" { /// Below are common applications of `transmute` which can be replaced with safer /// constructs. /// + /// Turning raw bytes(`&[u8]`) to `u32`, `f64`, etc.: + /// + /// ``` + /// let raw_bytes = [0x78, 0x56, 0x34, 0x12]; + /// + /// let num = unsafe { + /// std::mem::transmute::<[u8; 4], u32>(raw_bytes); + /// }; + /// + /// // use `u32::from_ne_bytes` instead + /// let num = u32::from_ne_bytes(raw_bytes); + /// // or use `u32::from_le_bytes` or `u32::from_ge_bytes` to specify the endianness + /// let num = u32::from_le_bytes(raw_bytes); + /// assert_eq!(num, 0x12345678); + /// let num = u32::from_be_bytes(raw_bytes); + /// assert_eq!(num, 0x78563412); + /// ``` + /// /// Turning a pointer into a `usize`: /// /// ``` diff --git a/src/librustc_error_codes/error_codes/E0522.md b/src/librustc_error_codes/error_codes/E0522.md index e4756c384c495..83272314a8708 100644 --- a/src/librustc_error_codes/error_codes/E0522.md +++ b/src/librustc_error_codes/error_codes/E0522.md @@ -1,7 +1,5 @@ -The lang attribute is intended for marking special items that are built-in to -Rust itself. This includes special traits (like `Copy` and `Sized`) that affect -how the compiler behaves, as well as special functions that may be automatically -invoked (such as the handler for out-of-bounds accesses when indexing a slice). +The lang attribute was used in an invalid context. + Erroneous code example: ```compile_fail,E0522 @@ -12,3 +10,8 @@ fn cookie() -> ! { // error: definition of an unknown language item: `cookie` loop {} } ``` + +The lang attribute is intended for marking special items that are built-in to +Rust itself. This includes special traits (like `Copy` and `Sized`) that affect +how the compiler behaves, as well as special functions that may be automatically +invoked (such as the handler for out-of-bounds accesses when indexing a slice). diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ca6bd21fefd39..9bb81c322ab1b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2251,26 +2251,39 @@ fn fn_sig_suggestion( sig: &ty::FnSig<'_>, ident: Ident, predicates: ty::GenericPredicates<'_>, + assoc: &ty::AssocItem, ) -> String { let args = sig .inputs() .iter() - .map(|ty| { + .enumerate() + .map(|(i, ty)| { Some(match ty.kind { - ty::Param(param) if param.name == kw::SelfUpper => "self".to_string(), - ty::Ref(reg, ref_ty, mutability) => { + ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(), + ty::Ref(reg, ref_ty, mutability) if i == 0 => { let reg = match &format!("{}", reg)[..] { "'_" | "" => String::new(), reg => format!("{} ", reg), }; - match ref_ty.kind { - ty::Param(param) if param.name == kw::SelfUpper => { - format!("&{}{}self", reg, mutability.prefix_str()) + if assoc.fn_has_self_parameter { + match ref_ty.kind { + ty::Param(param) if param.name == kw::SelfUpper => { + format!("&{}{}self", reg, mutability.prefix_str()) + } + + _ => format!("self: {}", ty), } - _ => format!("_: {:?}", ty), + } else { + format!("_: {:?}", ty) + } + } + _ => { + if assoc.fn_has_self_parameter && i == 0 { + format!("self: {:?}", ty) + } else { + format!("_: {:?}", ty) } } - _ => format!("_: {:?}", ty), }) }) .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 { tcx.fn_sig(assoc.def_id).skip_binder(), assoc.ident, tcx.predicates_of(assoc.def_id), + assoc, ) } ty::AssocKind::Type => format!("type {} = Type;", assoc.ident), diff --git a/src/test/ui/missing/missing-items/auxiliary/m1.rs b/src/test/ui/missing/missing-items/auxiliary/m1.rs index 7705066760c50..fcf52c9e88743 100644 --- a/src/test/ui/missing/missing-items/auxiliary/m1.rs +++ b/src/test/ui/missing/missing-items/auxiliary/m1.rs @@ -2,4 +2,8 @@ pub trait X { const CONSTANT: u32; type Type; fn method(&self, s: String) -> Self::Type; + fn method2(self: Box, s: String) -> Self::Type; + fn method3(other: &Self, s: String) -> Self::Type; + fn method4(&self, other: &Self) -> Self::Type; + fn method5(self: &Box) -> Self::Type; } diff --git a/src/test/ui/missing/missing-items/m2.stderr b/src/test/ui/missing/missing-items/m2.stderr index 094782099f6ed..64e9530e61348 100644 --- a/src/test/ui/missing/missing-items/m2.stderr +++ b/src/test/ui/missing/missing-items/m2.stderr @@ -1,12 +1,16 @@ -error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method` +error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` --> $DIR/m2.rs:9:1 | LL | impl m1::X for X { - | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method` in implementation + | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4`, `method5` in implementation | = help: implement the missing item: `const CONSTANT: u32 = 42;` = help: implement the missing item: `type Type = Type;` = help: implement the missing item: `fn method(&self, _: std::string::String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method2(self: std::boxed::Box, _: std::string::String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method3(_: &Self, _: std::string::String) -> ::Type { todo!() }` + = help: implement the missing item: `fn method4(&self, _: &Self) -> ::Type { todo!() }` + = help: implement the missing item: `fn method5(self: &std::boxed::Box) -> ::Type { todo!() }` error: aborting due to previous error