From 80ccddc0ed8627c0fc5e15c7526f2702ce64adb9 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Mon, 13 Apr 2020 17:17:34 +0200 Subject: [PATCH 1/8] weak-into-raw: as_raw -> as_ptr + dangling garbage * Rename Weak::as_raw to Weak::as_ptr for consistency with some other types. * The as_ptr for a dangling Weak pointer might return whatever garbage (and takes that advantage to avoid a conditional). * Don't guarantee to be able to do `Weak::from_raw(weak.as_ptr())` (even though it'll still work fine). --- src/liballoc/rc.rs | 41 +++++++++++++++-------------------------- src/liballoc/sync.rs | 41 +++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index abc4056cf5695..59424de42770c 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1644,8 +1644,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 +1658,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 +1682,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 +1703,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 +1721,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 +1755,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..203b386ba1d0e 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1340,8 +1340,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 +1354,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 +1378,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 +1399,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 +1418,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 +1448,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 From da59b8ff655522642b44e2236b75d3f8c59f0edc Mon Sep 17 00:00:00 2001 From: Duddino Date: Thu, 16 Apr 2020 11:28:49 +0200 Subject: [PATCH 2/8] fixed missing trait method suggests incorrect code (self parameter not named self) --- src/librustc_typeck/check/mod.rs | 26 ++++++++++++------- .../ui/missing/missing-items/auxiliary/m1.rs | 3 +++ src/test/ui/missing/missing-items/m2.stderr | 7 +++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ca6bd21fefd39..77540ecde6cfe 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2251,26 +2251,33 @@ 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) => { 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()) - } - _ => format!("_: {:?}", ty), + if assoc.fn_has_self_parameter && i == 0 { + format!("&{}{}self", reg, mutability.prefix_str()) + }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 +2316,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..177506d917637 100644 --- a/src/test/ui/missing/missing-items/auxiliary/m1.rs +++ b/src/test/ui/missing/missing-items/auxiliary/m1.rs @@ -2,4 +2,7 @@ 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; } diff --git a/src/test/ui/missing/missing-items/m2.stderr b/src/test/ui/missing/missing-items/m2.stderr index 094782099f6ed..3231836bc88d5 100644 --- a/src/test/ui/missing/missing-items/m2.stderr +++ b/src/test/ui/missing/missing-items/m2.stderr @@ -1,12 +1,15 @@ -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` --> $DIR/m2.rs:9:1 | LL | impl m1::X for X { - | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method` in implementation + | ^^^^^^^^^^^^^^^^ missing `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4` 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!() }` error: aborting due to previous error From ad105ef9a4ad313fea5fb48329ab0795c8012644 Mon Sep 17 00:00:00 2001 From: Duddino Date: Thu, 16 Apr 2020 11:34:26 +0200 Subject: [PATCH 3/8] ./x.py fmt --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 77540ecde6cfe..19d3c6b4afd6d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2267,7 +2267,7 @@ fn fn_sig_suggestion( }; if assoc.fn_has_self_parameter && i == 0 { format!("&{}{}self", reg, mutability.prefix_str()) - }else { + } else { format!("_: {:?}", ty) } } From f36f78f571f06b966d4f80a24dd9287546aeaf94 Mon Sep 17 00:00:00 2001 From: Duddino Date: Thu, 16 Apr 2020 14:04:12 +0200 Subject: [PATCH 4/8] Fixed issue with self: &Box --- src/librustc_typeck/check/mod.rs | 12 +++++++++--- src/test/ui/missing/missing-items/auxiliary/m1.rs | 1 + src/test/ui/missing/missing-items/m2.stderr | 5 +++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 19d3c6b4afd6d..9bb81c322ab1b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2260,13 +2260,19 @@ fn fn_sig_suggestion( .map(|(i, ty)| { Some(match ty.kind { ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(), - ty::Ref(reg, _ref_ty, mutability) => { + ty::Ref(reg, ref_ty, mutability) if i == 0 => { let reg = match &format!("{}", reg)[..] { "'_" | "" => String::new(), reg => format!("{} ", reg), }; - if assoc.fn_has_self_parameter && i == 0 { - 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), + } } else { format!("_: {:?}", ty) } diff --git a/src/test/ui/missing/missing-items/auxiliary/m1.rs b/src/test/ui/missing/missing-items/auxiliary/m1.rs index 177506d917637..fcf52c9e88743 100644 --- a/src/test/ui/missing/missing-items/auxiliary/m1.rs +++ b/src/test/ui/missing/missing-items/auxiliary/m1.rs @@ -5,4 +5,5 @@ pub trait X { 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 3231836bc88d5..64e9530e61348 100644 --- a/src/test/ui/missing/missing-items/m2.stderr +++ b/src/test/ui/missing/missing-items/m2.stderr @@ -1,8 +1,8 @@ -error[E0046]: not all trait items implemented, missing: `CONSTANT`, `Type`, `method`, `method2`, `method3`, `method4` +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`, `method2`, `method3`, `method4` 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;` @@ -10,6 +10,7 @@ LL | impl m1::X for X { = 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 From 1a1863b815d0db6aa1751e88e7044e9e2f02ac51 Mon Sep 17 00:00:00 2001 From: huangjiahua Date: Sat, 18 Apr 2020 14:58:38 +0800 Subject: [PATCH 5/8] Add example in the alternative in std::mem::transmute docs It is safer to use `from_ne_bytes` to convert raw bytes to type like u32. --- src/libcore/intrinsics.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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`: /// /// ``` From 49bca71418b270135d701582b3592577e2d067e3 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 18 Apr 2020 21:07:28 +0200 Subject: [PATCH 6/8] Clarify when to use the tracking issue template --- .github/ISSUE_TEMPLATE/tracking_issue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 --- From f4ded11b49aa24dcd8c0e114b427757b5d08dbe7 Mon Sep 17 00:00:00 2001 From: Michal 'vorner' Vaner Date: Mon, 13 Apr 2020 19:08:33 +0200 Subject: [PATCH 7/8] weak-into-raw: Add {Arc,Rc}::as_ptr For consistency with Weak --- src/liballoc/rc.rs | 26 +++++++++++++++++++++++++- src/liballoc/sync.rs | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 59424de42770c..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. diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 203b386ba1d0e..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. From ca6eb2c2b225b18014cbc4edfc2bb006f6bc9111 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 19 Apr 2020 13:18:45 +0200 Subject: [PATCH 8/8] Clean up E0522 explanation --- src/librustc_error_codes/error_codes/E0522.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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).