From 6293dca1e880394d90fe80055216328fe4d9702e Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Thu, 16 Jul 2020 21:29:09 +0200 Subject: [PATCH 01/29] Change Debug impl of SocketAddr and IpAddr to match their Display output This has already been done for `SocketAddrV4`, `SocketAddrV6`, `IpAddrV4` and `IpAddrV6`. I don't see a point to keep the rather bad to read derived impl, especially when pretty printing: V4( 127.0.0.1 ) From the `Display`, one can easily and unambiguously see if it's V4 or V6. Using `Display` as `Debug` is very convenient for configuration structs (e.g. for webservers) that often just have a `derive(Debug)` and are printed that way to the user. --- library/std/src/net/addr.rs | 9 ++++++++- library/std/src/net/ip.rs | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index 8c8d1aadf48e2..4f751656e09c8 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -37,7 +37,7 @@ use crate::vec; /// assert_eq!(socket.port(), 8080); /// assert_eq!(socket.is_ipv4(), true); /// ``` -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub enum SocketAddr { /// An IPv4 socket address. @@ -597,6 +597,13 @@ impl fmt::Display for SocketAddr { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for SocketAddrV4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 0f0be2c488314..c27a33bc10963 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -39,7 +39,7 @@ use crate::sys_common::{AsInner, FromInner}; /// assert_eq!(localhost_v4.is_ipv4(), true); /// ``` #[stable(feature = "ip_addr", since = "1.7.0")] -#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] +#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub enum IpAddr { /// An IPv4 address. #[stable(feature = "ip_addr", since = "1.7.0")] @@ -811,6 +811,13 @@ impl fmt::Display for IpAddr { } } +#[stable(feature = "ip_addr", since = "1.7.0")] +impl fmt::Debug for IpAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, fmt) + } +} + #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From for IpAddr { /// Copies this address to a new `IpAddr::V4`. From 3a02e06002e3c34cd63c1237d0998414c56f7efc Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 5 Aug 2020 18:07:33 +0200 Subject: [PATCH 02/29] BTreeMap: purge innocent use of into_kv_mut --- library/alloc/src/collections/btree/map.rs | 6 +++--- library/alloc/src/collections/btree/node.rs | 22 +++++++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e7d243bfcb0f7..8e800f48c69de 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -245,7 +245,7 @@ where fn replace(&mut self, key: K) -> Option { let root = Self::ensure_is_owned(&mut self.root); match search::search_tree::, K, (), K>(root.node_as_mut(), &key) { - Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), + Found(handle) => Some(mem::replace(handle.into_key_mut(), key)), GoDown(handle) => { VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData } .insert(()); @@ -811,7 +811,7 @@ impl BTreeMap { { let root_node = self.root.as_mut()?.node_as_mut(); match search::search_tree(root_node, key) { - Found(handle) => Some(handle.into_kv_mut().1), + Found(handle) => Some(handle.into_val_mut()), GoDown(_) => None, } } @@ -2748,7 +2748,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn into_mut(self) -> &'a mut V { - self.handle.into_kv_mut().1 + self.handle.into_val_mut() } /// Sets the value of the entry with the `OccupiedEntry`'s key, diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index f70869148d59f..d844433832471 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -1018,6 +1018,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeTyp } impl<'a, K: 'a, V: 'a, NodeType> Handle, K, V, NodeType>, marker::KV> { + pub fn into_key_mut(self) -> &'a mut K { + let keys = self.node.into_key_slice_mut(); + unsafe { keys.get_unchecked_mut(self.idx) } + } + + pub fn into_val_mut(self) -> &'a mut V { + let vals = self.node.into_val_slice_mut(); + unsafe { vals.get_unchecked_mut(self.idx) } + } + pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { unsafe { let (keys, vals) = self.node.into_slices_mut(); @@ -1216,8 +1226,8 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: unsafe { let (k, v, edge) = self.reborrow_mut().left_edge().descend().pop(); - let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k); - let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v); + let k = mem::replace(self.kv_mut().0, k); + let v = mem::replace(self.kv_mut().1, v); match self.reborrow_mut().right_edge().descend().force() { ForceResult::Leaf(mut leaf) => leaf.push_front(k, v), @@ -1233,8 +1243,8 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: unsafe { let (k, v, edge) = self.reborrow_mut().right_edge().descend().pop_front(); - let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k); - let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v); + let k = mem::replace(self.kv_mut().0, k); + let v = mem::replace(self.kv_mut().1, v); match self.reborrow_mut().left_edge().descend().force() { ForceResult::Leaf(mut leaf) => leaf.push(k, v), @@ -1262,7 +1272,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let left_kv = left_node.reborrow_mut().into_kv_pointers_mut(); let right_kv = right_node.reborrow_mut().into_kv_pointers_mut(); let parent_kv = { - let kv = self.reborrow_mut().into_kv_mut(); + let kv = self.kv_mut(); (kv.0 as *mut K, kv.1 as *mut V) }; @@ -1319,7 +1329,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let left_kv = left_node.reborrow_mut().into_kv_pointers_mut(); let right_kv = right_node.reborrow_mut().into_kv_pointers_mut(); let parent_kv = { - let kv = self.reborrow_mut().into_kv_mut(); + let kv = self.kv_mut(); (kv.0 as *mut K, kv.1 as *mut V) }; From e005b71125338d792360f8a6d946ad42d7bbba01 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 11 Aug 2020 18:02:24 -0700 Subject: [PATCH 03/29] Switch to intra-doc links in `std::process` --- library/std/src/process.rs | 95 +++++++++++++++----------------------- 1 file changed, 37 insertions(+), 58 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4ba1940fd0ece..37f6755597a93 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -84,25 +84,15 @@ //! assert_eq!(b"test", output.stdout.as_slice()); //! ``` //! -//! [`abort`]: fn.abort.html -//! [`exit`]: fn.exit.html +//! [`spawn`]: Command::spawn +//! [`output`]: Command::output //! -//! [`Command`]: struct.Command.html -//! [`spawn`]: struct.Command.html#method.spawn -//! [`output`]: struct.Command.html#method.output +//! [`stdout`]: Command::stdout +//! [`stdin`]: Command::stdin +//! [`stderr`]: Command::stderr //! -//! [`Child`]: struct.Child.html -//! [`ChildStdin`]: struct.ChildStdin.html -//! [`ChildStdout`]: struct.ChildStdout.html -//! [`ChildStderr`]: struct.ChildStderr.html -//! [`Stdio`]: struct.Stdio.html -//! -//! [`stdout`]: struct.Command.html#method.stdout -//! [`stdin`]: struct.Command.html#method.stdin -//! [`stderr`]: struct.Command.html#method.stderr -//! -//! [`Write`]: ../io/trait.Write.html -//! [`Read`]: ../io/trait.Read.html +//! [`Write`]: io::Write +//! [`Read`]: io::Read #![stable(feature = "process", since = "1.0.0")] @@ -130,7 +120,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// run, even after the `Child` handle to the child process has gone out of /// scope. /// -/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make +/// Calling [`wait`] (or other functions that wrap around it) will make /// the parent process wait until the child has actually exited before /// continuing. /// @@ -162,9 +152,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; /// assert!(ecode.success()); /// ``` /// -/// [`Command`]: struct.Command.html -/// [`Drop`]: ../../core/ops/trait.Drop.html -/// [`wait`]: #method.wait +/// [`wait`]: Child::wait #[stable(feature = "process", since = "1.0.0")] pub struct Child { handle: imp::Process, @@ -227,9 +215,8 @@ impl fmt::Debug for Child { /// file handle will be closed. If the child process was blocked on input prior /// to being dropped, it will become unblocked after dropping. /// -/// [`Child`]: struct.Child.html -/// [`stdin`]: struct.Child.html#structfield.stdin -/// [dropped]: ../ops/trait.Drop.html +/// [`stdin`]: crate::process::Child.stdin +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { inner: AnonPipe, @@ -286,9 +273,8 @@ impl fmt::Debug for ChildStdin { /// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s /// underlying file handle will be closed. /// -/// [`Child`]: struct.Child.html -/// [`stdout`]: struct.Child.html#structfield.stdout -/// [dropped]: ../ops/trait.Drop.html +/// [`stdout`]: crate::process::Child.stdout +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { inner: AnonPipe, @@ -347,9 +333,8 @@ impl fmt::Debug for ChildStdout { /// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s /// underlying file handle will be closed. /// -/// [`Child`]: struct.Child.html -/// [`stderr`]: struct.Child.html#structfield.stderr -/// [dropped]: ../ops/trait.Drop.html +/// [`stderr`]: crate::process::Child.stderr +/// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { inner: AnonPipe, @@ -522,7 +507,7 @@ impl Command { /// /// To pass multiple arguments see [`args`]. /// - /// [`args`]: #method.args + /// [`args`]: Command::args /// /// # Examples /// @@ -547,7 +532,7 @@ impl Command { /// /// To pass a single argument see [`arg`]. /// - /// [`arg`]: #method.arg + /// [`arg`]: Command::arg /// /// # Examples /// @@ -700,7 +685,7 @@ impl Command { /// .expect("ls command failed to start"); /// ``` /// - /// [`canonicalize`]: ../fs/fn.canonicalize.html + /// [`canonicalize`]: crate::fs::canonicalize #[stable(feature = "process", since = "1.0.0")] pub fn current_dir>(&mut self, dir: P) -> &mut Command { self.inner.cwd(dir.as_ref().as_ref()); @@ -712,8 +697,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -738,8 +723,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -764,8 +749,8 @@ impl Command { /// Defaults to [`inherit`] when used with `spawn` or `status`, and /// defaults to [`piped`] when used with `output`. /// - /// [`inherit`]: struct.Stdio.html#method.inherit - /// [`piped`]: struct.Stdio.html#method.piped + /// [`inherit`]: Stdio::inherit + /// [`piped`]: Stdio::piped /// /// # Examples /// @@ -893,10 +878,8 @@ impl AsInnerMut for Command { /// [`Command`], or the [`wait_with_output`] method of a [`Child`] /// process. /// -/// [`Command`]: struct.Command.html -/// [`Child`]: struct.Child.html -/// [`output`]: struct.Command.html#method.output -/// [`wait_with_output`]: struct.Child.html#method.wait_with_output +/// [`output`]: Command::output +/// [`wait_with_output`]: Child::wait_with_output #[derive(PartialEq, Eq, Clone)] #[stable(feature = "process", since = "1.0.0")] pub struct Output { @@ -939,10 +922,9 @@ impl fmt::Debug for Output { /// Describes what to do with a standard I/O stream for a child process when /// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`]. /// -/// [`stdin`]: struct.Command.html#method.stdin -/// [`stdout`]: struct.Command.html#method.stdout -/// [`stderr`]: struct.Command.html#method.stderr -/// [`Command`]: struct.Command.html +/// [`stdin`]: Command::stdin +/// [`stdout`]: Command::stdout +/// [`stderr`]: Command::stderr #[stable(feature = "process", since = "1.0.0")] pub struct Stdio(imp::Stdio); @@ -1206,10 +1188,8 @@ impl From for Stdio { /// status is exposed through the [`status`] method, or the [`wait`] method /// of a [`Child`] process. /// -/// [`Command`]: struct.Command.html -/// [`Child`]: struct.Child.html -/// [`status`]: struct.Command.html#method.status -/// [`wait`]: struct.Child.html#method.wait +/// [`status`]: Command::status +/// [`wait`]: Child::wait #[derive(PartialEq, Eq, Clone, Copy, Debug)] #[stable(feature = "process", since = "1.0.0")] pub struct ExitStatus(imp::ExitStatus); @@ -1294,8 +1274,8 @@ impl fmt::Display for ExitStatus { /// For the platform's canonical successful and unsuccessful codes, see /// the [`SUCCESS`] and [`FAILURE`] associated items. /// -/// [`SUCCESS`]: #associatedconstant.SUCCESS -/// [`FAILURE`]: #associatedconstant.FAILURE +/// [`SUCCESS`]: ExitCode::SUCCESS +/// [`FAILURE`]: ExitCode::FAILURE /// /// **Warning**: While various forms of this were discussed in [RFC #1937], /// it was ultimately cut from that RFC, and thus this type is more subject @@ -1349,9 +1329,9 @@ impl Child { /// } /// ``` /// - /// [`ErrorKind`]: ../io/enum.ErrorKind.html - /// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput - /// [`Other`]: ../io/enum.ErrorKind.html#variant.Other + /// [`ErrorKind`]: io::ErrorKind + /// [`InvalidInput`]: io::ErrorKind::InvalidInput + /// [`Other`]: io::ErrorKind::Other #[stable(feature = "process", since = "1.0.0")] pub fn kill(&mut self) -> io::Result<()> { self.handle.kill() @@ -1616,8 +1596,7 @@ pub fn exit(code: i32) -> ! { /// } /// ``` /// -/// [`panic!`]: ../../std/macro.panic.html -/// [panic hook]: ../../std/panic/fn.set_hook.html +/// [panic hook]: crate::panic::set_hook #[stable(feature = "process_abort", since = "1.17.0")] pub fn abort() -> ! { crate::sys::abort_internal(); From d8f96146e8b34e8f648d65f24af5c14fde4f44d5 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 11 Aug 2020 20:10:41 -0700 Subject: [PATCH 04/29] Use `Child::std{in,out,err}` instead of `Child.` These links were broken before. --- library/std/src/process.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 37f6755597a93..f6555a175e810 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -215,7 +215,7 @@ impl fmt::Debug for Child { /// file handle will be closed. If the child process was blocked on input prior /// to being dropped, it will become unblocked after dropping. /// -/// [`stdin`]: crate::process::Child.stdin +/// [`stdin`]: Child::stdin /// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdin { @@ -273,7 +273,7 @@ impl fmt::Debug for ChildStdin { /// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s /// underlying file handle will be closed. /// -/// [`stdout`]: crate::process::Child.stdout +/// [`stdout`]: Child::stdout /// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStdout { @@ -333,7 +333,7 @@ impl fmt::Debug for ChildStdout { /// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s /// underlying file handle will be closed. /// -/// [`stderr`]: crate::process::Child.stderr +/// [`stderr`]: Child::stderr /// [dropped]: Drop #[stable(feature = "process", since = "1.0.0")] pub struct ChildStderr { From bbad31df2f0661976814832786a6067e4bc255f1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Aug 2020 13:07:27 +0200 Subject: [PATCH 05/29] Clean up E0752 explanation --- src/librustc_error_codes/error_codes/E0752.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md index 86945f83b5524..77512fddcf63a 100644 --- a/src/librustc_error_codes/error_codes/E0752.md +++ b/src/librustc_error_codes/error_codes/E0752.md @@ -1,11 +1,19 @@ -`fn main()` or the specified start function is not allowed to be -async. You might be seeing this error because your async runtime -library is not set up correctly. +The entry point of the program was marked as `async`. Erroneous code example: ```compile_fail,E0752 -async fn main() -> Result { +async fn main() -> Result { // error! + Ok(1) +} +``` + +`fn main()` or the specified start function is not allowed to be `async`. You +might be seeing this error because your async runtime library is not set up +correctly. To fix it, don't declare the entry point as `async`: + +``` +fn main() -> Result { // ok! Ok(1) } ``` From 406719bf24dc33e333e70804faf7697e795bc422 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Aug 2020 20:13:44 +0200 Subject: [PATCH 06/29] Improve wording --- src/librustc_error_codes/error_codes/E0752.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md index 77512fddcf63a..d79ad06bee095 100644 --- a/src/librustc_error_codes/error_codes/E0752.md +++ b/src/librustc_error_codes/error_codes/E0752.md @@ -8,9 +8,9 @@ async fn main() -> Result { // error! } ``` -`fn main()` or the specified start function is not allowed to be `async`. You -might be seeing this error because your async runtime library is not set up -correctly. To fix it, don't declare the entry point as `async`: +`fn main()` or the specified start function is not allowed to be `async`. Not +having a correct async runtime library setup may cause this error. To fix it, +declare the entry point without `async`: ``` fn main() -> Result { // ok! From 0ce97fc5112e3162b8396afe23848ac0b594a7ea Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Aug 2020 21:07:56 +0200 Subject: [PATCH 07/29] Fix code examples --- src/librustc_error_codes/error_codes/E0752.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0752.md b/src/librustc_error_codes/error_codes/E0752.md index d79ad06bee095..9736da80c2b7b 100644 --- a/src/librustc_error_codes/error_codes/E0752.md +++ b/src/librustc_error_codes/error_codes/E0752.md @@ -3,8 +3,8 @@ The entry point of the program was marked as `async`. Erroneous code example: ```compile_fail,E0752 -async fn main() -> Result { // error! - Ok(1) +async fn main() -> Result<(), ()> { // error! + Ok(()) } ``` @@ -13,7 +13,7 @@ having a correct async runtime library setup may cause this error. To fix it, declare the entry point without `async`: ``` -fn main() -> Result { // ok! - Ok(1) +fn main() -> Result<(), ()> { // ok! + Ok(()) } ``` From 2adc8c0e5fd34d88a601d9c572bb2f29d23d0357 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Thu, 13 Aug 2020 23:19:45 +0200 Subject: [PATCH 08/29] Move to intra doc links in std::ffi --- library/std/src/ffi/c_str.rs | 193 +++++++++------------------------- library/std/src/ffi/mod.rs | 42 +++----- library/std/src/ffi/os_str.rs | 79 +++----------- 3 files changed, 81 insertions(+), 233 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index da25a0ede729d..194573da76736 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -35,23 +35,23 @@ use crate::sys; /// example, you can build a `CString` straight out of a [`String`] or /// a [`&str`], since both implement that trait). /// -/// The [`new`] method will actually check that the provided `&[u8]` +/// The [`CString::new`] method will actually check that the provided `&[u8]` /// does not have 0 bytes in the middle, and return an error if it /// finds one. /// /// # Extracting a raw pointer to the whole C string /// -/// `CString` implements a [`as_ptr`] method through the [`Deref`] +/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`] /// trait. This method will give you a `*const c_char` which you can /// feed directly to extern functions that expect a nul-terminated -/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a +/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a /// read-only pointer; if the C code writes to it, that causes /// undefined behavior. /// /// # Extracting a slice of the whole C string /// /// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a -/// `CString` with the [`as_bytes`] method. Slices produced in this +/// `CString` with the [`CString::as_bytes`] method. Slices produced in this /// way do *not* contain the trailing nul terminator. This is useful /// when you will be calling an extern function that takes a `*const /// u8` argument which is not necessarily nul-terminated, plus another @@ -60,7 +60,7 @@ use crate::sys; /// [`len`][slice.len] method. /// /// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you -/// can use [`as_bytes_with_nul`] instead. +/// can use [`CString::as_bytes_with_nul`] instead. /// /// Once you have the kind of slice you need (with or without a nul /// terminator), you can call the slice's own @@ -68,20 +68,11 @@ use crate::sys; /// extern functions. See the documentation for that function for a /// discussion on ensuring the lifetime of the raw pointer. /// -/// [`Into`]: ../convert/trait.Into.html -/// [`Vec`]: ../vec/struct.Vec.html -/// [`String`]: ../string/struct.String.html -/// [`&str`]: ../primitive.str.html -/// [`u8`]: ../primitive.u8.html -/// [`new`]: #method.new -/// [`as_bytes`]: #method.as_bytes -/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul -/// [`as_ptr`]: #method.as_ptr +/// [`&str`]: str /// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr /// [slice.len]: ../primitive.slice.html#method.len -/// [`Deref`]: ../ops/trait.Deref.html -/// [`CStr`]: struct.CStr.html -/// [`&CStr`]: struct.CStr.html +/// [`Deref`]: ops::Deref +/// [`&CStr`]: CStr /// /// # Examples /// @@ -113,7 +104,6 @@ use crate::sys; /// documentation of `CString` before use, as improper ownership management /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. - #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct CString { @@ -137,8 +127,8 @@ pub struct CString { /// /// Note that this structure is **not** `repr(C)` and is not recommended to be /// placed in the signatures of FFI functions. Instead, safe wrappers of FFI -/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe -/// interface to other consumers. +/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide +/// a safe interface to other consumers. /// /// # Examples /// @@ -189,11 +179,7 @@ pub struct CString { /// println!("string: {}", my_string_safe()); /// ``` /// -/// [`u8`]: ../primitive.u8.html -/// [`&str`]: ../primitive.str.html -/// [`String`]: ../string/struct.String.html -/// [`CString`]: struct.CString.html -/// [`from_ptr`]: #method.from_ptr +/// [`&str`]: str #[derive(Hash)] #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -218,9 +204,6 @@ pub struct CStr { /// This error is created by the [`new`][`CString::new`] method on /// [`CString`]. See its documentation for more. /// -/// [`CString`]: struct.CString.html -/// [`CString::new`]: struct.CString.html#method.new -/// /// # Examples /// /// ``` @@ -237,12 +220,9 @@ pub struct NulError(usize, Vec); /// The slice used to create a [`CStr`] must have one and only one nul byte, /// positioned at the end. /// -/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`]. +/// This error is created by the [`CStr::from_bytes_with_nul`] method. /// See its documentation for more. /// -/// [`CStr`]: struct.CStr.html -/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul -/// /// # Examples /// /// ``` @@ -261,12 +241,9 @@ pub struct FromBytesWithNulError { /// The vector used to create a [`CString`] must have one and only one nul byte, /// positioned at the end. /// -/// This error is created by the [`from_vec_with_nul`] method on [`CString`]. +/// This error is created by the [`CString::from_vec_with_nul`] method. /// See its documentation for more. /// -/// [`CString`]: struct.CString.html -/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul -/// /// # Examples /// /// ``` @@ -316,8 +293,6 @@ impl FromVecWithNulError { /// /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` - /// - /// [`CString`]: struct.CString.html pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -343,8 +318,6 @@ impl FromVecWithNulError { /// /// assert_eq!(bytes, value.unwrap_err().into_bytes()); /// ``` - /// - /// [`CString`]: struct.CString.html pub fn into_bytes(self) -> Vec { self.bytes } @@ -352,17 +325,12 @@ impl FromVecWithNulError { /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`]. /// -/// `CString` is just a wrapper over a buffer of bytes with a nul -/// terminator; [`into_string`][`CString::into_string`] performs UTF-8 -/// validation on those bytes and may return this error. +/// `CString` is just a wrapper over a buffer of bytes with a nul terminator; +/// [`CString::into_string`] performs UTF-8 validation on those bytes and may +/// return this error. /// -/// This `struct` is created by the -/// [`into_string`][`CString::into_string`] method on [`CString`]. See +/// This `struct` is created by the [`CString::into_string`] method. See /// its documentation for more. -/// -/// [`String`]: ../string/struct.String.html -/// [`CString`]: struct.CString.html -/// [`CString::into_string`]: struct.CString.html#method.into_string #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstring_into", since = "1.7.0")] pub struct IntoStringError { @@ -398,8 +366,6 @@ impl CString { /// This function will return an error if the supplied bytes contain an /// internal 0 byte. The [`NulError`] returned will contain the bytes as well as /// the position of the nul byte. - /// - /// [`NulError`]: struct.NulError.html #[stable(feature = "rust1", since = "1.0.0")] pub fn new>>(t: T) -> Result { trait SpecIntoVec { @@ -439,11 +405,9 @@ impl CString { /// Creates a C-compatible string by consuming a byte vector, /// without checking for interior 0 bytes. /// - /// This method is equivalent to [`new`] except that no runtime assertion - /// is made that `v` contains no 0 bytes, and it requires an actual - /// byte vector, not anything that can be converted to one with Into. - /// - /// [`new`]: #method.new + /// This method is equivalent to [`CString::new`] except that no runtime + /// assertion is made that `v` contains no 0 bytes, and it requires an + /// actual byte vector, not anything that can be converted to one with Into. /// /// # Examples /// @@ -462,21 +426,22 @@ impl CString { CString { inner: v.into_boxed_slice() } } - /// Retakes ownership of a `CString` that was transferred to C via [`into_raw`]. + /// Retakes ownership of a `CString` that was transferred to C via + /// [`CString::into_raw`]. /// /// Additionally, the length of the string will be recalculated from the pointer. /// /// # Safety /// /// This should only ever be called with a pointer that was earlier - /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take + /// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take /// ownership of a string that was allocated by foreign code) is likely to lead /// to undefined behavior or allocator corruption. /// /// It should be noted that the length isn't just "recomputed," but that /// the recomputed length must match the original length from the - /// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods - /// should not be used when passing the string to C functions that can + /// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw` + /// methods should not be used when passing the string to C functions that can /// modify the string's length. /// /// > **Note:** If you need to borrow a string that was allocated by @@ -485,9 +450,6 @@ impl CString { /// > make your own provisions for freeing it appropriately, likely /// > with the foreign code's API to do that. /// - /// [`into_raw`]: #method.into_raw - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake @@ -518,18 +480,16 @@ impl CString { /// Consumes the `CString` and transfers ownership of the string to a C caller. /// /// The pointer which this function returns must be returned to Rust and reconstituted using - /// [`from_raw`] to be properly deallocated. Specifically, one + /// [`CString::from_raw`] to be properly deallocated. Specifically, one /// should *not* use the standard C `free()` function to deallocate /// this string. /// - /// Failure to call [`from_raw`] will lead to a memory leak. + /// Failure to call [`CString::from_raw`] will lead to a memory leak. /// /// The C side must **not** modify the length of the string (by writing a /// `NULL` somewhere inside the string or removing the final one) before - /// it makes it back into Rust using [`from_raw`]. See the safety section - /// in [`from_raw`]. - /// - /// [`from_raw`]: #method.from_raw + /// it makes it back into Rust using [`CString::from_raw`]. See the safety section + /// in [`CString::from_raw`]. /// /// # Examples /// @@ -560,8 +520,6 @@ impl CString { /// /// On failure, ownership of the original `CString` is returned. /// - /// [`String`]: ../string/struct.String.html - /// /// # Examples /// /// ``` @@ -608,10 +566,8 @@ impl CString { vec } - /// Equivalent to the [`into_bytes`] function except that the returned vector - /// includes the trailing nul terminator. - /// - /// [`into_bytes`]: #method.into_bytes + /// Equivalent to the [`CString::into_bytes`] function except that the + /// returned vector includes the trailing nul terminator. /// /// # Examples /// @@ -632,9 +588,7 @@ impl CString { /// The returned slice does **not** contain the trailing nul /// terminator, and it is guaranteed to not have any interior nul /// bytes. If you need the nul terminator, use - /// [`as_bytes_with_nul`] instead. - /// - /// [`as_bytes_with_nul`]: #method.as_bytes_with_nul + /// [`CString::as_bytes_with_nul`] instead. /// /// # Examples /// @@ -651,10 +605,8 @@ impl CString { &self.inner[..self.inner.len() - 1] } - /// Equivalent to the [`as_bytes`] function except that the returned slice - /// includes the trailing nul terminator. - /// - /// [`as_bytes`]: #method.as_bytes + /// Equivalent to the [`CString::as_bytes`] function except that the + /// returned slice includes the trailing nul terminator. /// /// # Examples /// @@ -673,8 +625,6 @@ impl CString { /// Extracts a [`CStr`] slice containing the entire string. /// - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// ``` @@ -693,8 +643,6 @@ impl CString { /// Converts this `CString` into a boxed [`CStr`]. /// - /// [`CStr`]: struct.CStr.html - /// /// # Examples /// /// ``` @@ -711,8 +659,6 @@ impl CString { } /// Bypass "move out of struct which implements [`Drop`] trait" restriction. - /// - /// [`Drop`]: ../ops/trait.Drop.html fn into_inner(self) -> Box<[u8]> { // Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)` // so we use `ManuallyDrop` to ensure `self` is not dropped. @@ -722,12 +668,12 @@ impl CString { unsafe { ptr::read(&this.inner) } } - /// Converts a `Vec` of `u8` to a `CString` without checking the invariants - /// on the given `Vec`. + /// Converts a [`Vec`]`` to a [`CString`] without checking the + /// invariants on the given [`Vec`]. /// /// # Safety /// - /// The given `Vec` **must** have one nul byte as its last element. + /// The given [`Vec`] **must** have one nul byte as its last element. /// This means it cannot be empty nor have any other nul byte anywhere else. /// /// # Example @@ -745,10 +691,10 @@ impl CString { Self { inner: v.into_boxed_slice() } } - /// Attempts to converts a `Vec` of `u8` to a `CString`. + /// Attempts to converts a [`Vec`]`` to a [`CString`]. /// /// Runtime checks are present to ensure there is only one nul byte in the - /// `Vec`, its last element. + /// [`Vec`], its last element. /// /// # Errors /// @@ -757,8 +703,8 @@ impl CString { /// /// # Examples /// - /// A successful conversion will produce the same result as [`new`] when - /// called without the ending nul byte. + /// A successful conversion will produce the same result as [`CString::new`] + /// when called without the ending nul byte. /// /// ``` /// #![feature(cstring_from_vec_with_nul)] @@ -770,7 +716,7 @@ impl CString { /// ); /// ``` /// - /// A incorrectly formatted vector will produce an error. + /// A incorrectly formatted [`Vec`] will produce an error. /// /// ``` /// #![feature(cstring_from_vec_with_nul)] @@ -780,8 +726,6 @@ impl CString { /// // No nul byte /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err(); /// ``` - /// - /// [`new`]: #method.new #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")] pub fn from_vec_with_nul(v: Vec) -> Result { let nul_pos = memchr::memchr(0, &v); @@ -838,9 +782,6 @@ impl From for Vec { /// Converts a [`CString`] into a [`Vec`]``. /// /// The conversion consumes the [`CString`], and removes the terminating NUL byte. - /// - /// [`Vec`]: ../vec/struct.Vec.html - /// [`CString`]: ../ffi/struct.CString.html #[inline] fn from(s: CString) -> Vec { s.into_bytes() @@ -913,9 +854,6 @@ impl From> for Box { #[stable(feature = "c_string_from_box", since = "1.18.0")] impl From> for CString { /// Converts a [`Box`]`` into a [`CString`] without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`CString`]: ../ffi/struct.CString.html #[inline] fn from(s: Box) -> CString { s.into_c_string() @@ -926,10 +864,6 @@ impl From> for CString { impl From> for CString { /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without /// copying nor checking for inner null bytes. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html - /// [`Vec`]: ../vec/struct.Vec.html #[inline] fn from(v: Vec) -> CString { unsafe { @@ -959,9 +893,6 @@ impl Clone for Box { #[stable(feature = "box_from_c_string", since = "1.20.0")] impl From for Box { /// Converts a [`CString`] into a [`Box`]`` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Box`]: ../boxed/struct.Box.html #[inline] fn from(s: CString) -> Box { s.into_boxed_c_str() @@ -995,9 +926,6 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { /// Converts a [`CString`] into a [`Arc`]`` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Arc`]: ../sync/struct.Arc.html #[inline] fn from(s: CString) -> Arc { let arc: Arc<[u8]> = Arc::from(s.into_inner()); @@ -1017,9 +945,6 @@ impl From<&CStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { /// Converts a [`CString`] into a [`Rc`]`` without copying or allocating. - /// - /// [`CString`]: ../ffi/struct.CString.html - /// [`Rc`]: ../rc/struct.Rc.html #[inline] fn from(s: CString) -> Rc { let rc: Rc<[u8]> = Rc::from(s.into_inner()); @@ -1048,8 +973,6 @@ impl NulError { /// Returns the position of the nul byte in the slice that caused /// [`CString::new`] to fail. /// - /// [`CString::new`]: struct.CString.html#method.new - /// /// # Examples /// /// ``` @@ -1101,9 +1024,6 @@ impl fmt::Display for NulError { #[stable(feature = "rust1", since = "1.0.0")] impl From for io::Error { /// Converts a [`NulError`] into a [`io::Error`]. - /// - /// [`NulError`]: ../ffi/struct.NulError.html - /// [`io::Error`]: ../io/struct.Error.html fn from(_: NulError) -> io::Error { io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte") } @@ -1154,8 +1074,6 @@ impl fmt::Display for FromVecWithNulError { impl IntoStringError { /// Consumes this error, returning original [`CString`] which generated the /// error. - /// - /// [`CString`]: struct.CString.html #[stable(feature = "cstring_into", since = "1.7.0")] pub fn into_cstring(self) -> CString { self.inner @@ -1330,7 +1248,8 @@ impl CStr { /// /// This happens because the pointer returned by `as_ptr` does not carry any /// lifetime information and the [`CString`] is deallocated immediately after - /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated. + /// the `CString::new("Hello").expect("CString::new failed").as_ptr()` + /// expression is evaluated. /// To fix the problem, bind the `CString` to a local variable: /// /// ```no_run @@ -1345,10 +1264,8 @@ impl CStr { /// } /// ``` /// - /// This way, the lifetime of the `CString` in `hello` encompasses + /// This way, the lifetime of the [`CString`] in `hello` encompasses /// the lifetime of `ptr` and the `unsafe` block. - /// - /// [`CString`]: struct.CString.html #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] @@ -1382,15 +1299,13 @@ impl CStr { /// Converts this C string to a byte slice containing the trailing 0 byte. /// - /// This function is the equivalent of [`to_bytes`] except that it will retain - /// the trailing nul terminator instead of chopping it off. + /// This function is the equivalent of [`CStr::to_bytes`] except that it + /// will retain the trailing nul terminator instead of chopping it off. /// /// > **Note**: This method is currently implemented as a 0-cost cast, but /// > it is planned to alter its definition in the future to perform the /// > length calculation whenever this method is called. /// - /// [`to_bytes`]: #method.to_bytes - /// /// # Examples /// /// ``` @@ -1411,7 +1326,7 @@ impl CStr { /// function will return the corresponding [`&str`] slice. Otherwise, /// it will return an error with details of where UTF-8 validation failed. /// - /// [`&str`]: ../primitive.str.html + /// [`&str`]: str /// /// # Examples /// @@ -1439,12 +1354,9 @@ impl CStr { /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result. /// - /// [`Cow`]: ../borrow/enum.Cow.html - /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed - /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned - /// [`str`]: ../primitive.str.html - /// [`String`]: ../string/struct.String.html - /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html + /// [`Borrowed`]: Cow::Borrowed + /// [`Owned`]: Cow::Owned + /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER /// /// # Examples /// @@ -1479,9 +1391,6 @@ impl CStr { /// Converts a [`Box`]`` into a [`CString`] without copying or allocating. /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`CString`]: struct.CString.html - /// /// # Examples /// /// ``` diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index f442d7fde1a5e..0184495eecf09 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -88,7 +88,7 @@ //! [`env::var_os()`] is used to query environment variables; it //! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable //! exists you will get a [`Some`]`(os_string)`, which you can *then* try to -//! convert to a Rust string. This yields a [`Result<>`], so that +//! convert to a Rust string. This yields a [`Result`], so that //! your code can detect errors in case the environment variable did //! not in fact contain valid Unicode data. //! @@ -124,34 +124,22 @@ //! method is an [`OsString`] which can be round-tripped to a Windows //! string losslessly. //! -//! [`String`]: ../string/struct.String.html -//! [`str`]: ../primitive.str.html -//! [`char`]: ../primitive.char.html -//! [`u8`]: ../primitive.u8.html -//! [`u16`]: ../primitive.u16.html //! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value //! [Unicode code point]: http://www.unicode.org/glossary/#code_point -//! [`CString`]: struct.CString.html -//! [`CStr`]: struct.CStr.html -//! [`OsString`]: struct.OsString.html -//! [`OsStr`]: struct.OsStr.html -//! [`env::set_var()`]: ../env/fn.set_var.html -//! [`env::var_os()`]: ../env/fn.var_os.html -//! [`Result<>`]: ../result/enum.Result.html -//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html -//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec -//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec -//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html -//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes -//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes -//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html -//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html -//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide -//! [`collect`]: ../iter/trait.Iterator.html#method.collect -//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html -//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide -//! [`Option`]: ../option/enum.Option.html -//! [`Some`]: ../option/enum.Option.html#variant.Some +//! [`env::set_var()`]: crate::env::set_var +//! [`env::var_os()`]: crate::env::var_os +//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt +//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec +//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec +//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt +//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes +//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes +//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt +//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt +//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide +//! [`collect`]: crate::iter::Iterator::collect +//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt +//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide #![stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index d1eaf3c583f2d..262d39d98ee2e 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -47,14 +47,14 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// create an `OsString` from a normal Rust string. /// /// **From slices:** Just like you can start with an empty Rust -/// [`String`] and then [`push_str`][String.push_str] `&str` +/// [`String`] and then [`String::push_str`] `&str` /// sub-string slices into it, you can create an empty `OsString` with -/// the [`new`] method and then push string slices into it with the -/// [`push`] method. +/// the [`OsString::new`] method and then push string slices into it with the +/// [`OsString::push`] method. /// /// # Extracting a borrowed reference to the whole OS string /// -/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from +/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from /// an `OsString`; this is effectively a borrowed reference to the /// whole string. /// @@ -63,18 +63,9 @@ use crate::sys_common::{AsInner, FromInner, IntoInner}; /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsString` implements for [conversions] from/to native representations. /// -/// [`OsStr`]: struct.OsStr.html -/// [`&OsStr`]: struct.OsStr.html -/// [`CStr`]: struct.CStr.html -/// [`From`]: ../convert/trait.From.html -/// [`String`]: ../string/struct.String.html -/// [`&str`]: ../primitive.str.html -/// [`u8`]: ../primitive.u8.html -/// [`u16`]: ../primitive.u16.html -/// [String.push_str]: ../string/struct.String.html#method.push_str -/// [`new`]: #method.new -/// [`push`]: #method.push -/// [`as_os_str`]: #method.as_os_str +/// [`&OsStr`]: OsStr +/// [`&str`]: str +/// [`CStr`]: crate::ffi::CStr /// [conversions]: index.html#conversions #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] @@ -93,9 +84,7 @@ pub struct OsString { /// See the [module's toplevel documentation about conversions][conversions] for a discussion on /// the traits which `OsStr` implements for [conversions] from/to native representations. /// -/// [`OsString`]: struct.OsString.html -/// [`&str`]: ../primitive.str.html -/// [`String`]: ../string/struct.String.html +/// [`&str`]: str /// [conversions]: index.html#conversions #[stable(feature = "rust1", since = "1.0.0")] // FIXME: @@ -125,8 +114,6 @@ impl OsString { /// Converts to an [`OsStr`] slice. /// - /// [`OsStr`]: struct.OsStr.html - /// /// # Examples /// /// ``` @@ -145,8 +132,6 @@ impl OsString { /// /// On failure, ownership of the original `OsString` is returned. /// - /// [`String`]: ../../std/string/struct.String.html - /// /// # Examples /// /// ``` @@ -163,7 +148,7 @@ impl OsString { /// Extends the string with the given [`&OsStr`] slice. /// - /// [`&OsStr`]: struct.OsStr.html + /// [`&OsStr`]: OsStr /// /// # Examples /// @@ -333,8 +318,6 @@ impl OsString { /// Converts this `OsString` into a boxed [`OsStr`]. /// - /// [`OsStr`]: struct.OsStr.html - /// /// # Examples /// /// ``` @@ -356,8 +339,6 @@ impl From for OsString { /// Converts a [`String`] into a [`OsString`]. /// /// The conversion copies the data, and includes an allocation on the heap. - /// - /// [`OsString`]: ../../std/ffi/struct.OsString.html fn from(s: String) -> OsString { OsString { inner: Buf::from_string(s) } } @@ -544,7 +525,7 @@ impl OsStr { /// /// This conversion may entail doing a check for UTF-8 validity. /// - /// [`&str`]: ../../std/primitive.str.html + /// [`&str`]: str /// /// # Examples /// @@ -564,9 +545,7 @@ impl OsStr { /// Any non-Unicode sequences are replaced with /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD]. /// - /// [`Cow`]: ../../std/borrow/enum.Cow.html - /// [`str`]: ../../std/primitive.str.html - /// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html + /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER /// /// # Examples /// @@ -613,8 +592,6 @@ impl OsStr { /// Copies the slice into an owned [`OsString`]. /// - /// [`OsString`]: struct.OsString.html - /// /// # Examples /// /// ``` @@ -662,9 +639,6 @@ impl OsStr { /// This number is simply useful for passing to other methods, like /// [`OsString::with_capacity`] to avoid reallocations. /// - /// [`OsString`]: struct.OsString.html - /// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity - /// /// # Examples /// /// ``` @@ -682,9 +656,6 @@ impl OsStr { } /// Converts a [`Box`]`` into an [`OsString`] without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsString`]: struct.OsString.html #[stable(feature = "into_boxed_os_str", since = "1.20.0")] pub fn into_os_string(self: Box) -> OsString { let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) }; @@ -706,9 +677,7 @@ impl OsStr { /// but non-ASCII letters are unchanged. /// /// To return a new lowercased value without modifying the existing one, use - /// [`to_ascii_lowercase`]. - /// - /// [`to_ascii_lowercase`]: #method.to_ascii_lowercase + /// [`OsStr::to_ascii_lowercase`]. /// /// # Examples /// @@ -733,9 +702,7 @@ impl OsStr { /// but non-ASCII letters are unchanged. /// /// To return a new uppercased value without modifying the existing one, use - /// [`to_ascii_uppercase`]. - /// - /// [`to_ascii_uppercase`]: #method.to_ascii_uppercase + /// [`OsStr::to_ascii_uppercase`]. /// /// # Examples /// @@ -760,9 +727,7 @@ impl OsStr { /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', /// but non-ASCII letters are unchanged. /// - /// To lowercase the value in-place, use [`make_ascii_lowercase`]. - /// - /// [`make_ascii_lowercase`]: #method.make_ascii_lowercase + /// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`]. /// /// # Examples /// @@ -784,9 +749,7 @@ impl OsStr { /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z', /// but non-ASCII letters are unchanged. /// - /// To uppercase the value in-place, use [`make_ascii_uppercase`]. - /// - /// [`make_ascii_uppercase`]: #method.make_ascii_uppercase + /// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`]. /// /// # Examples /// @@ -865,9 +828,6 @@ impl From> for Box { impl From> for OsString { /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or /// allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsStr`]: ../ffi/struct.OsStr.html fn from(boxed: Box) -> OsString { boxed.into_os_string() } @@ -876,9 +836,6 @@ impl From> for OsString { #[stable(feature = "box_from_os_string", since = "1.20.0")] impl From for Box { /// Converts a [`OsString`] into a [`Box`]`` without copying or allocating. - /// - /// [`Box`]: ../boxed/struct.Box.html - /// [`OsString`]: ../ffi/struct.OsString.html fn from(s: OsString) -> Box { s.into_boxed_os_str() } @@ -895,9 +852,6 @@ impl Clone for Box { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { /// Converts a [`OsString`] into a [`Arc`]`` without copying or allocating. - /// - /// [`Arc`]: ../sync/struct.Arc.html - /// [`OsString`]: ../ffi/struct.OsString.html #[inline] fn from(s: OsString) -> Arc { let arc = s.inner.into_arc(); @@ -917,9 +871,6 @@ impl From<&OsStr> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { /// Converts a [`OsString`] into a [`Rc`]`` without copying or allocating. - /// - /// [`Rc`]: ../rc/struct.Rc.html - /// [`OsString`]: ../ffi/struct.OsString.html #[inline] fn from(s: OsString) -> Rc { let rc = s.inner.into_rc(); From 643258ff6c6f545debeb2ce5b7405522843d6ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Aug 2020 17:04:33 -0700 Subject: [PATCH 09/29] Tweak suggestion for `this` -> `self` --- src/librustc_resolve/late/diagnostics.rs | 30 +++++++++++++++++++--- src/test/ui/issues/issue-5099.rs | 9 ++++++- src/test/ui/issues/issue-5099.stderr | 32 +++++++++++++++++++++--- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index c57c0e5194185..ce154bb09f450 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -7,6 +7,7 @@ use crate::{PathResult, PathSource, Segment}; use rustc_ast::ast::{self, Expr, ExprKind, Item, ItemKind, NodeId, Path, Ty, TyKind}; use rustc_ast::util::lev_distance::find_best_match_for_name; +use rustc_ast::visit::FnKind; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -175,15 +176,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code); // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&&*item_str.as_str()) - && self.self_value_is_available(path[0].ident.span, span) - { + if ["this", "my"].contains(&&*item_str.as_str()) && self.self_type_is_available(span) { err.span_suggestion_short( span, "you might have meant to use `self` here instead", "self".to_string(), Applicability::MaybeIncorrect, ); + if !self.self_value_is_available(path[0].ident.span, span) { + if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) = + &self.diagnostic_metadata.current_function + { + if let Some(param) = sig.decl.inputs.get(0) { + err.span_suggestion_verbose( + param.span.shrink_to_lo(), + "you are also missing a `self` receiver argument", + "&self, ".to_string(), + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + self.r + .session + .source_map() + .span_through_char(*fn_span, '(') + .shrink_to_hi(), + "you are also missing a `self` receiver argument", + "&self".to_string(), + Applicability::MaybeIncorrect, + ); + } + } + } } // Emit special messages for unresolved `Self` and `self`. diff --git a/src/test/ui/issues/issue-5099.rs b/src/test/ui/issues/issue-5099.rs index d00fff3280920..ee134835c37ed 100644 --- a/src/test/ui/issues/issue-5099.rs +++ b/src/test/ui/issues/issue-5099.rs @@ -1,3 +1,10 @@ -trait B < A > { fn a() -> A { this.a } } //~ ERROR cannot find value `this` in this scope +trait B { + fn a() -> A { + this.a //~ ERROR cannot find value `this` in this scope + } + fn b(x: i32) { + this.b(x); //~ ERROR cannot find value `this` in this scope + } +} fn main() {} diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr index cc11db9c5eca6..56b02c45a08d7 100644 --- a/src/test/ui/issues/issue-5099.stderr +++ b/src/test/ui/issues/issue-5099.stderr @@ -1,9 +1,33 @@ error[E0425]: cannot find value `this` in this scope - --> $DIR/issue-5099.rs:1:31 + --> $DIR/issue-5099.rs:3:9 | -LL | trait B < A > { fn a() -> A { this.a } } - | ^^^^ not found in this scope +LL | this.a + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.a + | ^^^^ +help: you are also missing a `self` receiver argument + | +LL | fn a(&self) -> A { + | ^^^^^ + +error[E0425]: cannot find value `this` in this scope + --> $DIR/issue-5099.rs:6:9 + | +LL | this.b(x); + | ^^^^ not found in this scope + | +help: you might have meant to use `self` here instead + | +LL | self.b(x); + | ^^^^ +help: you are also missing a `self` receiver argument + | +LL | fn b(&self, x: i32) { + | ^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0425`. From 360388b160ca5be560fec59acb84a86e813524f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Aug 2020 17:52:33 -0700 Subject: [PATCH 10/29] Suggest adding `&self` when accessing `self` in static assoc `fn` --- src/librustc_ast/visit.rs | 7 +++ src/librustc_resolve/late/diagnostics.rs | 61 ++++++++++++++++++------ src/test/ui/error-codes/E0424.rs | 4 ++ src/test/ui/error-codes/E0424.stderr | 40 +++++++++++----- src/test/ui/resolve/issue-2356.stderr | 27 +++++------ 5 files changed, 98 insertions(+), 41 deletions(-) diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs index 2c3d1e97df975..b65a88cb90e88 100644 --- a/src/librustc_ast/visit.rs +++ b/src/librustc_ast/visit.rs @@ -50,6 +50,13 @@ impl<'a> FnKind<'a> { } } + pub fn ident(&self) -> Option<&Ident> { + match self { + FnKind::Fn(_, ident, ..) => Some(ident), + _ => None, + } + } + pub fn decl(&self) -> &'a FnDecl { match self { FnKind::Fn(_, _, sig, _, _) => &sig.decl, diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index ce154bb09f450..67a9d9b4ec1b4 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -175,8 +175,9 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let code = source.error_code(res.is_some()); let mut err = self.r.session.struct_span_err_with_code(base_span, &base_msg, code); + let is_assoc_fn = self.self_type_is_available(span); // Emit help message for fake-self from other languages (e.g., `this` in Javascript). - if ["this", "my"].contains(&&*item_str.as_str()) && self.self_type_is_available(span) { + if ["this", "my"].contains(&&*item_str.as_str()) && is_assoc_fn { err.span_suggestion_short( span, "you might have meant to use `self` here instead", @@ -187,25 +188,24 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if let Some((FnKind::Fn(_, _, sig, ..), fn_span)) = &self.diagnostic_metadata.current_function { - if let Some(param) = sig.decl.inputs.get(0) { - err.span_suggestion_verbose( - param.span.shrink_to_lo(), - "you are also missing a `self` receiver argument", - "&self, ".to_string(), - Applicability::MaybeIncorrect, - ); + let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) { + (param.span.shrink_to_lo(), "&self, ") } else { - err.span_suggestion_verbose( + ( self.r .session .source_map() .span_through_char(*fn_span, '(') .shrink_to_hi(), - "you are also missing a `self` receiver argument", - "&self".to_string(), - Applicability::MaybeIncorrect, - ); - } + "&self", + ) + }; + err.span_suggestion_verbose( + span, + "you are also missing a `self` receiver argument", + sugg.to_string(), + Applicability::MaybeIncorrect, + ); } } } @@ -236,7 +236,38 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if fn_kind.decl().inputs.get(0).map(|p| p.is_self()).unwrap_or(false) { err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters"); } else { - err.span_label(*span, "this function doesn't have a `self` parameter"); + let doesnt = if is_assoc_fn { + let (span, sugg) = fn_kind + .decl() + .inputs + .get(0) + .map(|p| (p.span.shrink_to_lo(), "&self, ")) + .unwrap_or_else(|| { + ( + self.r + .session + .source_map() + .span_through_char(*span, '(') + .shrink_to_hi(), + "&self", + ) + }); + err.span_suggestion_verbose( + span, + "add a `self` receiver parameter to make the associated `fn` a method", + sugg.to_string(), + Applicability::MaybeIncorrect, + ); + "doesn't" + } else { + "can't" + }; + if let Some(ident) = fn_kind.ident() { + err.span_label( + ident.span, + &format!("this function {} have a `self` parameter", doesnt), + ); + } } } return (err, Vec::new()); diff --git a/src/test/ui/error-codes/E0424.rs b/src/test/ui/error-codes/E0424.rs index 3c6a1d4f88f11..fa0c86ecf4894 100644 --- a/src/test/ui/error-codes/E0424.rs +++ b/src/test/ui/error-codes/E0424.rs @@ -6,6 +6,10 @@ impl Foo { fn foo() { self.bar(); //~ ERROR E0424 } + + fn baz(_: i32) { + self.bar(); //~ ERROR E0424 + } } fn main () { diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 690a101496d73..9b8a29e827249 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -1,21 +1,37 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | -LL | / fn foo() { -LL | | self.bar(); - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | } - | |_____- this function doesn't have a `self` parameter +LL | fn foo() { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn foo(&self) { + | ^^^^^ + +error[E0424]: expected value, found module `self` + --> $DIR/E0424.rs:11:9 + | +LL | fn baz(_: i32) { + | --- this function doesn't have a `self` parameter +LL | self.bar(); + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn baz(&self, _: i32) { + | ^^^^^^ error[E0424]: expected unit struct, unit variant or constant, found module `self` - --> $DIR/E0424.rs:12:9 + --> $DIR/E0424.rs:16:9 | -LL | / fn main () { -LL | | let self = "self"; - | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed -LL | | } - | |_- this function doesn't have a `self` parameter +LL | fn main () { + | ---- this function can't have a `self` parameter +LL | let self = "self"; + | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0424`. diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index b687f0b0af0ad..0339daa0d6a18 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -70,14 +70,15 @@ LL | purr(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | -LL | / fn meow() { -LL | | if self.whiskers > 3 { - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | println!("MEOW"); -LL | | } -LL | | } - | |___- this function doesn't have a `self` parameter +LL | fn meow() { + | ---- this function doesn't have a `self` parameter +LL | if self.whiskers > 3 { + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter + | +help: add a `self` receiver parameter to make the associated `fn` a method + | +LL | fn meow(&self) { + | ^^^^^ error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -112,12 +113,10 @@ LL | purr_louder(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | -LL | / fn main() { -LL | | self += 1; - | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter -LL | | -LL | | } - | |_- this function doesn't have a `self` parameter +LL | fn main() { + | ---- this function can't have a `self` parameter +LL | self += 1; + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error: aborting due to 17 previous errors From b77c40e42d9249de3ac38829c8cfa22aa609e3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Aug 2020 18:30:00 -0700 Subject: [PATCH 11/29] Do not emit E0228 when it is implied by E0106 Emit E0288 (lifetime bound for trait object cannot be deduced) only on bare trait objects. When the trait object is in the form of `&dyn Trait`, E0106 (missing lifetime specifier) will have been emitted, making the former redundant. --- src/librustc_typeck/astconv.rs | 24 +++++-- .../suggestions/missing-lifetime-specifier.rs | 8 +-- .../missing-lifetime-specifier.stderr | 72 +++++-------------- 3 files changed, 37 insertions(+), 67 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2be100ae33662..3093ddbeaf1ae 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1623,6 +1623,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { span: Span, trait_bounds: &[hir::PolyTraitRef<'_>], lifetime: &hir::Lifetime, + borrowed: bool, ) -> Ty<'tcx> { let tcx = self.tcx(); @@ -1837,15 +1838,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(lifetime, None) } else { self.re_infer(None, span).unwrap_or_else(|| { - // FIXME: these can be redundant with E0106, but not always. - struct_span_err!( + let mut err = struct_span_err!( tcx.sess, span, E0228, "the lifetime bound for this object type cannot be deduced \ from context; please supply an explicit bound" - ) - .emit(); + ); + if borrowed { + // We will have already emitted an error E0106 complaining about a + // missing named lifetime in `&dyn Trait`, so we elide this one. + err.delay_as_bug(); + } else { + err.emit(); + } tcx.lifetimes.re_static }) } @@ -2873,6 +2879,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Parses the programmer's textual representation of a type into our /// internal notion of a type. pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> { + self.ast_ty_to_ty_inner(ast_ty, false) + } + + /// Turns a `hir::Ty` into a `Ty`. For diagnostics' purposes we keep track of whether trait + /// objects are borrowed like `&dyn Trait` to avoid emitting redundant errors. + fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool) -> Ty<'tcx> { debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})", ast_ty.hir_id, ast_ty, ast_ty.kind); let tcx = self.tcx(); @@ -2885,7 +2897,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); debug!("ast_ty_to_ty: r={:?}", r); - let t = self.ast_ty_to_ty(&mt.ty); + let t = self.ast_ty_to_ty_inner(&mt.ty, true); tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, @@ -2903,7 +2915,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { )) } hir::TyKind::TraitObject(ref bounds, ref lifetime) => { - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime) + self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed) } hir::TyKind::Path(hir::QPath::Resolved(ref maybe_qself, ref path)) => { debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.rs b/src/test/ui/suggestions/missing-lifetime-specifier.rs index b09c1879d7015..fe88d105c78bf 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.rs +++ b/src/test/ui/suggestions/missing-lifetime-specifier.rs @@ -25,8 +25,6 @@ thread_local! { //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context } thread_local! { static c: RefCell>>>> = RefCell::new(HashMap::new()); @@ -39,8 +37,6 @@ thread_local! { //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier //~| ERROR missing lifetime specifier - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context } thread_local! { @@ -52,9 +48,7 @@ thread_local! { } thread_local! { static f: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR the lifetime bound for this object type cannot be deduced from context - //~| ERROR wrong number of lifetime arguments: expected 2, found 1 + //~^ ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 //~| ERROR wrong number of lifetime arguments: expected 2, found 1 diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index 2630cf1affae6..9838ac72ad767 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -71,7 +71,7 @@ LL | static b: RefCell>>>> = Ref | ^^^^^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:48 + --> $DIR/missing-lifetime-specifier.rs:30:48 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -83,7 +83,7 @@ LL | static c: RefCell>>>> = | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:48 + --> $DIR/missing-lifetime-specifier.rs:30:48 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -95,7 +95,7 @@ LL | static c: RefCell>>>> = | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:37:44 + --> $DIR/missing-lifetime-specifier.rs:35:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -107,7 +107,7 @@ LL | static d: RefCell>>>> = RefCell: | ^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:37:49 + --> $DIR/missing-lifetime-specifier.rs:35:49 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -119,7 +119,7 @@ LL | static d: RefCell>>>> | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:37:44 + --> $DIR/missing-lifetime-specifier.rs:35:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -131,7 +131,7 @@ LL | static d: RefCell>>>> = RefCell: | ^^^^^^^^ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:37:49 + --> $DIR/missing-lifetime-specifier.rs:35:49 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -143,7 +143,7 @@ LL | static d: RefCell>>>> | ^^^^^^^^^^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:54:44 + --> $DIR/missing-lifetime-specifier.rs:50:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -155,7 +155,7 @@ LL | static f: RefCell>>>> = | ^^^^^^^^ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:54:44 + --> $DIR/missing-lifetime-specifier.rs:50:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -166,91 +166,55 @@ help: consider using the `'static` lifetime LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^ -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:23:45 - | -LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:37:45 - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:37:45 - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:47:44 + --> $DIR/missing-lifetime-specifier.rs:43:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:54:45 - | -LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/missing-lifetime-specifier.rs:54:45 - | -LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); - | ^^^^^^^^^^^^^^^^^ - error[E0107]: wrong number of lifetime arguments: expected 2, found 1 - --> $DIR/missing-lifetime-specifier.rs:54:45 + --> $DIR/missing-lifetime-specifier.rs:50:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^^^^^^^^^^^^^^^ expected 2 lifetime arguments -error: aborting due to 28 previous errors +error: aborting due to 22 previous errors -Some errors have detailed explanations: E0106, E0107, E0228. +Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. From dba647ef32e8f076bdc1338249932ed08b61a127 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Thu, 9 Jul 2020 23:41:56 +0800 Subject: [PATCH 12/29] Remove liballoc unneeded explicit link --- library/alloc/src/vec.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 786d1b6ba82f2..b5c2f1d725618 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2621,7 +2621,6 @@ where /// This `struct` is created by the `into_iter` method on [`Vec`] (provided /// by the [`IntoIterator`] trait). /// -/// [`Vec`]: struct.Vec.html /// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { @@ -2805,7 +2804,6 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter { /// This `struct` is created by the [`drain`] method on [`Vec`]. /// /// [`drain`]: struct.Vec.html#method.drain -/// [`Vec`]: struct.Vec.html #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { /// Index of tail to preserve @@ -2937,7 +2935,6 @@ impl FusedIterator for Drain<'_, T> {} /// documentation for more. /// /// [`splice()`]: struct.Vec.html#method.splice -/// [`Vec`]: struct.Vec.html #[derive(Debug)] #[stable(feature = "vec_splice", since = "1.21.0")] pub struct Splice<'a, I: Iterator + 'a> { From e0d215ff9e6ab644b244518616f7979966220e79 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 24 Jul 2020 00:23:24 +0800 Subject: [PATCH 13/29] Update src/liballoc/vec.rs Co-authored-by: Joshua Nelson --- library/alloc/src/vec.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index b5c2f1d725618..d9f22be3ff699 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2621,7 +2621,6 @@ where /// This `struct` is created by the `into_iter` method on [`Vec`] (provided /// by the [`IntoIterator`] trait). /// -/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { buf: NonNull, From d2ecfcf21dc6c9c2a136c8cfefe2b9f8af7ca549 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 24 Jul 2020 17:28:37 +0800 Subject: [PATCH 14/29] Update liballoc vec doc link --- library/alloc/src/vec.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index d9f22be3ff699..15a01166a17c6 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2620,7 +2620,6 @@ where /// /// This `struct` is created by the `into_iter` method on [`Vec`] (provided /// by the [`IntoIterator`] trait). -/// #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter { buf: NonNull, @@ -2800,9 +2799,7 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter { /// A draining iterator for `Vec`. /// -/// This `struct` is created by the [`drain`] method on [`Vec`]. -/// -/// [`drain`]: struct.Vec.html#method.drain +/// This `struct` is created by [`Vec::drain`]. #[stable(feature = "drain", since = "1.6.0")] pub struct Drain<'a, T: 'a> { /// Index of tail to preserve @@ -2930,10 +2927,8 @@ impl FusedIterator for Drain<'_, T> {} /// A splicing iterator for `Vec`. /// -/// This struct is created by the [`splice()`] method on [`Vec`]. See its -/// documentation for more. -/// -/// [`splice()`]: struct.Vec.html#method.splice +/// This struct is created by [`Vec::splice()`]. +/// See its documentation for more. #[derive(Debug)] #[stable(feature = "vec_splice", since = "1.21.0")] pub struct Splice<'a, I: Iterator + 'a> { From 28bca67708aa4565311ef4fc53cec57b75fdedfd Mon Sep 17 00:00:00 2001 From: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Fri, 14 Aug 2020 00:37:19 -0700 Subject: [PATCH 15/29] Bump std's libc version to 0.2.74 --- library/std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index fc07fa77b85e7..ef0ef415b4cba 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.32" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } From 6e11329b54c2fc4e3ed73f84c1bce13f253cfed7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Aug 2020 11:17:03 +0200 Subject: [PATCH 16/29] mention 'lifetime extension' in promotion doc comments --- src/librustc_mir/transform/promote_consts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index c056410570157..94637bae44a78 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -101,7 +101,7 @@ impl TempState { /// of a larger candidate. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum Candidate { - /// Borrow of a constant temporary. + /// Borrow of a constant temporary, candidate for lifetime extension. Ref(Location), /// Promotion of the `x` in `[x; 32]`. From 7805c200d982f11ab6dc3ead72bca89e9be4d294 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Aug 2020 11:18:55 +0200 Subject: [PATCH 17/29] answer an old question re: intern kinds --- src/librustc_mir/interpret/intern.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index dffbc969c21b8..6c8ee72bc66c2 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -312,7 +312,8 @@ pub fn intern_const_alloc_recursive>( let tcx = ecx.tcx; let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), - // FIXME: what about array lengths, array initializers? + // `Constant` includes array lengths. + // `Promoted` includes non-`Copy` array initializers and `rustc_args_required_const` arguments. InternKind::Constant | InternKind::Promoted => InternMode::ConstBase, }; From d0d9048d6ced47e95d90c0213dc3b35f979bbb40 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Aug 2020 13:23:26 +0200 Subject: [PATCH 18/29] add a FIXME concerning interning of promoteds --- src/librustc_mir/const_eval/eval_queries.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 7fbe5c409d3ce..4101f70b8206d 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -57,6 +57,12 @@ fn eval_body_using_ecx<'mir, 'tcx>( ecx.run()?; // Intern the result + // FIXME: since the DefId of a promoted is the DefId of its owner, this + // means that promoteds in statics are actually interned like statics! + // However, this is also currently crucial because we promote mutable + // non-empty slices in statics to extend their lifetime, and this + // ensures that they are put into a mutable allocation. + // For other kinds of promoteds in statics (like array initializers), this is rather silly. let intern_kind = match tcx.static_mutability(cid.instance.def_id()) { Some(m) => InternKind::Static(m), None if cid.promoted.is_some() => InternKind::Promoted, From 90e4c905d352dc5c5de71af717200c879fec88f7 Mon Sep 17 00:00:00 2001 From: Jonas Berlin Date: Thu, 9 Jul 2020 21:18:06 +0300 Subject: [PATCH 19/29] Improve documentation on process::Child.std* fields As a relative beginner, it took a while for me to figure out I could just steal the references to avoid partially moving the child and thus retain ability to call functions on it (and store it in structs etc). --- library/std/src/process.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4ba1940fd0ece..409a945018654 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -170,17 +170,38 @@ pub struct Child { handle: imp::Process, /// The handle for writing to the child's standard input (stdin), if it has - /// been captured. + /// been captured. To avoid partially moving + /// the `child` and thus blocking yourself from calling + /// functions on `child` while using `stdin`, + /// you might find it helpful: + /// + /// ```compile_fail,E0425 + /// let stdin = child.stdin.take().unwrap(); + /// ``` #[stable(feature = "process", since = "1.0.0")] pub stdin: Option, /// The handle for reading from the child's standard output (stdout), if it - /// has been captured. + /// has been captured. You might find it helpful to do + /// + /// ```compile_fail,E0425 + /// let stdout = child.stdout.take().unwrap(); + /// ``` + /// + /// to avoid partially moving the `child` and thus blocking yourself from calling + /// functions on `child` while using `stdout`. #[stable(feature = "process", since = "1.0.0")] pub stdout: Option, /// The handle for reading from the child's standard error (stderr), if it - /// has been captured. + /// has been captured. You might find it helpful to do + /// + /// ```compile_fail,E0425 + /// let stderr = child.stderr.take().unwrap(); + /// ``` + /// + /// to avoid partially moving the `child` and thus blocking yourself from calling + /// functions on `child` while using `stderr`. #[stable(feature = "process", since = "1.0.0")] pub stderr: Option, } From 421e0ff3d9aab9f0a1d262d9b4e0f34b49eb2465 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 14 Aug 2020 14:50:30 +0200 Subject: [PATCH 20/29] BTreeMap: refactor splitpoint and move testing over to unit test --- library/alloc/src/collections/btree/node.rs | 42 +++++-------------- .../alloc/src/collections/btree/node/tests.rs | 25 +++++++++++ library/alloc/src/lib.rs | 1 + 3 files changed, 37 insertions(+), 31 deletions(-) create mode 100644 library/alloc/src/collections/btree/node/tests.rs diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index aa959c667accf..5a6a71c5fb687 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -43,6 +43,9 @@ use crate::boxed::Box; const B: usize = 6; pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; +const KV_IDX_CENTER: usize = B - 1; +const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1; +const EDGE_IDX_RIGHT_OF_CENTER: usize = B; /// The underlying representation of leaf nodes. #[repr(C)] @@ -834,38 +837,12 @@ enum InsertionPlace { fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) { debug_assert!(edge_idx <= CAPACITY); // Rust issue #74834 tries to explain these symmetric rules. - let middle_kv_idx; - let insertion; - if edge_idx <= B - 2 { - middle_kv_idx = B - 2; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B - 1 { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Right(0); - } else { - middle_kv_idx = B; - let new_edge_idx = edge_idx - (B + 1); - insertion = InsertionPlace::Right(new_edge_idx); - } - let mut left_len = middle_kv_idx; - let mut right_len = CAPACITY - middle_kv_idx - 1; - match insertion { - InsertionPlace::Left(edge_idx) => { - debug_assert!(edge_idx <= left_len); - left_len += 1; - } - InsertionPlace::Right(edge_idx) => { - debug_assert!(edge_idx <= right_len); - right_len += 1; - } + match edge_idx { + 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)), + EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)), + EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)), + _ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))), } - debug_assert!(left_len >= MIN_LEN); - debug_assert!(right_len >= MIN_LEN); - debug_assert!(left_len + right_len == CAPACITY); - (middle_kv_idx, insertion) } impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::Edge> { @@ -1594,3 +1571,6 @@ unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { ret } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs new file mode 100644 index 0000000000000..e2416974ddca3 --- /dev/null +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -0,0 +1,25 @@ +use super::*; + +#[test] +fn test_splitpoint() { + for idx in 0..=CAPACITY { + let (middle_kv_idx, insertion) = splitpoint(idx); + + // Simulate performing the split: + let mut left_len = middle_kv_idx; + let mut right_len = CAPACITY - middle_kv_idx - 1; + match insertion { + InsertionPlace::Left(edge_idx) => { + assert!(edge_idx <= left_len); + left_len += 1; + } + InsertionPlace::Right(edge_idx) => { + assert!(edge_idx <= right_len); + right_len += 1; + } + } + assert!(left_len >= MIN_LEN); + assert!(right_len >= MIN_LEN); + assert!(left_len + right_len == CAPACITY); + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 9ac23886d4e15..75a2c6be41c56 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,6 +93,7 @@ #![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(exclusive_range_pattern)] #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] From 8d1c3c116b6a3e26ab23f662fbf03d645068b228 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 14 Aug 2020 14:50:30 +0200 Subject: [PATCH 21/29] BTreeMap: refactor splitpoint and move testing over to unit test --- library/alloc/src/collections/btree/node.rs | 42 +++++-------------- .../alloc/src/collections/btree/node/tests.rs | 25 +++++++++++ library/alloc/src/lib.rs | 1 + 3 files changed, 37 insertions(+), 31 deletions(-) create mode 100644 library/alloc/src/collections/btree/node/tests.rs diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index c0b75fd5eacec..88d0ed9eb0c2a 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -43,6 +43,9 @@ use crate::boxed::Box; const B: usize = 6; pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; +const KV_IDX_CENTER: usize = B - 1; +const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1; +const EDGE_IDX_RIGHT_OF_CENTER: usize = B; /// The underlying representation of leaf nodes. #[repr(C)] @@ -834,38 +837,12 @@ enum InsertionPlace { fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) { debug_assert!(edge_idx <= CAPACITY); // Rust issue #74834 tries to explain these symmetric rules. - let middle_kv_idx; - let insertion; - if edge_idx <= B - 2 { - middle_kv_idx = B - 2; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B - 1 { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Left(edge_idx); - } else if edge_idx == B { - middle_kv_idx = B - 1; - insertion = InsertionPlace::Right(0); - } else { - middle_kv_idx = B; - let new_edge_idx = edge_idx - (B + 1); - insertion = InsertionPlace::Right(new_edge_idx); - } - let mut left_len = middle_kv_idx; - let mut right_len = CAPACITY - middle_kv_idx - 1; - match insertion { - InsertionPlace::Left(edge_idx) => { - debug_assert!(edge_idx <= left_len); - left_len += 1; - } - InsertionPlace::Right(edge_idx) => { - debug_assert!(edge_idx <= right_len); - right_len += 1; - } + match edge_idx { + 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)), + EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)), + EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)), + _ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))), } - debug_assert!(left_len >= MIN_LEN); - debug_assert!(right_len >= MIN_LEN); - debug_assert!(left_len + right_len == CAPACITY); - (middle_kv_idx, insertion) } impl<'a, K, V, NodeType> Handle, K, V, NodeType>, marker::Edge> { @@ -1590,3 +1567,6 @@ unsafe fn slice_remove(slice: &mut [T], idx: usize) -> T { ret } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs new file mode 100644 index 0000000000000..e2416974ddca3 --- /dev/null +++ b/library/alloc/src/collections/btree/node/tests.rs @@ -0,0 +1,25 @@ +use super::*; + +#[test] +fn test_splitpoint() { + for idx in 0..=CAPACITY { + let (middle_kv_idx, insertion) = splitpoint(idx); + + // Simulate performing the split: + let mut left_len = middle_kv_idx; + let mut right_len = CAPACITY - middle_kv_idx - 1; + match insertion { + InsertionPlace::Left(edge_idx) => { + assert!(edge_idx <= left_len); + left_len += 1; + } + InsertionPlace::Right(edge_idx) => { + assert!(edge_idx <= right_len); + right_len += 1; + } + } + assert!(left_len >= MIN_LEN); + assert!(right_len >= MIN_LEN); + assert!(left_len + right_len == CAPACITY); + } +} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 9ac23886d4e15..75a2c6be41c56 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -93,6 +93,7 @@ #![feature(container_error_extra)] #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] +#![feature(exclusive_range_pattern)] #![feature(extend_one)] #![feature(fmt_internals)] #![feature(fn_traits)] From 232e3d04b359a5867b530f26698f986ba1732d85 Mon Sep 17 00:00:00 2001 From: Prabakaran Kumaresshan <4676330+nixphix@users.noreply.github.com> Date: Fri, 14 Aug 2020 21:09:35 +0530 Subject: [PATCH 22/29] Switch to intra-doc links in os/raw/*.md --- library/std/src/os/raw/char.md | 8 ++++---- library/std/src/os/raw/double.md | 4 ++-- library/std/src/os/raw/float.md | 2 +- library/std/src/os/raw/int.md | 6 +++--- library/std/src/os/raw/long.md | 6 +++--- library/std/src/os/raw/longlong.md | 6 +++--- library/std/src/os/raw/schar.md | 4 ++-- library/std/src/os/raw/short.md | 4 ++-- library/std/src/os/raw/uchar.md | 4 ++-- library/std/src/os/raw/uint.md | 6 +++--- library/std/src/os/raw/ulong.md | 6 +++--- library/std/src/os/raw/ulonglong.md | 6 +++--- library/std/src/os/raw/ushort.md | 4 ++-- 13 files changed, 33 insertions(+), 33 deletions(-) diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md index 9a55767d965a6..9fb0aed89d885 100644 --- a/library/std/src/os/raw/char.md +++ b/library/std/src/os/raw/char.md @@ -5,7 +5,7 @@ Equivalent to C's `char` type. C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information. [C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types -[Rust's `char` type]: ../../primitive.char.html -[`CStr`]: ../../ffi/struct.CStr.html -[`i8`]: ../../primitive.i8.html -[`u8`]: ../../primitive.u8.html +[Rust's `char` type]: char +[`CStr`]: crate::ffi::CStr +[`i8`]: i8 +[`u8`]: u8 diff --git a/library/std/src/os/raw/double.md b/library/std/src/os/raw/double.md index 6818dada31793..51503b5bd69dc 100644 --- a/library/std/src/os/raw/double.md +++ b/library/std/src/os/raw/double.md @@ -3,5 +3,5 @@ Equivalent to C's `double` type. This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard. [IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754 -[`float`]: type.c_float.html -[`f64`]: ../../primitive.f64.html +[`float`]: c_float +[`f64`]: f64 diff --git a/library/std/src/os/raw/float.md b/library/std/src/os/raw/float.md index 57d1071d0da17..7483b97623e7c 100644 --- a/library/std/src/os/raw/float.md +++ b/library/std/src/os/raw/float.md @@ -3,4 +3,4 @@ Equivalent to C's `float` type. This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all. [IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754 -[`f32`]: ../../primitive.f32.html +[`f32`]: f32 diff --git a/library/std/src/os/raw/int.md b/library/std/src/os/raw/int.md index a0d25fd21d89f..9860e4782f335 100644 --- a/library/std/src/os/raw/int.md +++ b/library/std/src/os/raw/int.md @@ -2,6 +2,6 @@ Equivalent to C's `signed int` (`int`) type. This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example. -[`short`]: type.c_short.html -[`i32`]: ../../primitive.i32.html -[`i16`]: ../../primitive.i16.html +[`short`]: c_short +[`i32`]: i32 +[`i16`]: i16 diff --git a/library/std/src/os/raw/long.md b/library/std/src/os/raw/long.md index c620b402819fd..410100ac64aba 100644 --- a/library/std/src/os/raw/long.md +++ b/library/std/src/os/raw/long.md @@ -2,6 +2,6 @@ Equivalent to C's `signed long` (`long`) type. This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`. -[`int`]: type.c_int.html -[`i32`]: ../../primitive.i32.html -[`i64`]: ../../primitive.i64.html +[`int`]: c_int +[`i32`]: i32 +[`i64`]: i64 diff --git a/library/std/src/os/raw/longlong.md b/library/std/src/os/raw/longlong.md index ab3d6436568df..26463dc8ec003 100644 --- a/library/std/src/os/raw/longlong.md +++ b/library/std/src/os/raw/longlong.md @@ -2,6 +2,6 @@ Equivalent to C's `signed long long` (`long long`) type. This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type. -[`long`]: type.c_int.html -[`i64`]: ../../primitive.i64.html -[`i128`]: ../../primitive.i128.html +[`long`]: c_int +[`i64`]: i64 +[`i128`]: i128 diff --git a/library/std/src/os/raw/schar.md b/library/std/src/os/raw/schar.md index 6aa8b1211d808..cc8d9bf5f42ec 100644 --- a/library/std/src/os/raw/schar.md +++ b/library/std/src/os/raw/schar.md @@ -2,5 +2,5 @@ Equivalent to C's `signed char` type. This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`]. -[`char`]: type.c_char.html -[`i8`]: ../../primitive.i8.html +[`char`]: c_char +[`i8`]: i8 diff --git a/library/std/src/os/raw/short.md b/library/std/src/os/raw/short.md index be92c6c106d59..f2d25e387e2b3 100644 --- a/library/std/src/os/raw/short.md +++ b/library/std/src/os/raw/short.md @@ -2,5 +2,5 @@ Equivalent to C's `signed short` (`short`) type. This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example. -[`char`]: type.c_char.html -[`i16`]: ../../primitive.i16.html +[`char`]: c_char +[`i16`]: i16 diff --git a/library/std/src/os/raw/uchar.md b/library/std/src/os/raw/uchar.md index b6ca711f86934..462410820dc6a 100644 --- a/library/std/src/os/raw/uchar.md +++ b/library/std/src/os/raw/uchar.md @@ -2,5 +2,5 @@ Equivalent to C's `unsigned char` type. This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`]. -[`char`]: type.c_char.html -[`u8`]: ../../primitive.u8.html +[`char`]: c_char +[`u8`]: u8 diff --git a/library/std/src/os/raw/uint.md b/library/std/src/os/raw/uint.md index 6f7013a8ac18d..4a5c4ab1d4893 100644 --- a/library/std/src/os/raw/uint.md +++ b/library/std/src/os/raw/uint.md @@ -2,6 +2,6 @@ Equivalent to C's `unsigned int` type. This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example. -[`int`]: type.c_int.html -[`u32`]: ../../primitive.u32.html -[`u16`]: ../../primitive.u16.html +[`int`]: c_int +[`u32`]: u32 +[`u16`]: u16 diff --git a/library/std/src/os/raw/ulong.md b/library/std/src/os/raw/ulong.md index c350395080e80..745759c51abdc 100644 --- a/library/std/src/os/raw/ulong.md +++ b/library/std/src/os/raw/ulong.md @@ -2,6 +2,6 @@ Equivalent to C's `unsigned long` type. This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`. -[`long`]: type.c_long.html -[`u32`]: ../../primitive.u32.html -[`u64`]: ../../primitive.u64.html +[`long`]: c_long +[`u32`]: u32 +[`u64`]: u64 diff --git a/library/std/src/os/raw/ulonglong.md b/library/std/src/os/raw/ulonglong.md index c41faf74c5c68..981106b23b6a4 100644 --- a/library/std/src/os/raw/ulonglong.md +++ b/library/std/src/os/raw/ulonglong.md @@ -2,6 +2,6 @@ Equivalent to C's `unsigned long long` type. This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type. -[`long long`]: type.c_longlong.html -[`u64`]: ../../primitive.u64.html -[`u128`]: ../../primitive.u128.html +[`long long`]: c_longlong +[`u64`]: u64 +[`u128`]: u128 diff --git a/library/std/src/os/raw/ushort.md b/library/std/src/os/raw/ushort.md index d364abb3c8e0c..6e2506d52cf84 100644 --- a/library/std/src/os/raw/ushort.md +++ b/library/std/src/os/raw/ushort.md @@ -2,5 +2,5 @@ Equivalent to C's `unsigned short` type. This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`]. -[`short`]: type.c_short.html -[`u16`]: ../../primitive.u16.html +[`short`]: c_short +[`u16`]: u16 From ff45df2acf8cb31e50930840d48d5285b67b23ec Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 14 Aug 2020 16:38:53 +0200 Subject: [PATCH 23/29] Move btree unit test to their native, privileged location --- library/alloc/src/collections/btree/map.rs | 3 +++ .../collections/btree/map/tests.rs} | 14 ++++++---- library/alloc/src/collections/btree/mod.rs | 27 +++++++++++++++++++ library/alloc/src/collections/btree/set.rs | 3 +++ .../collections/btree/set/tests.rs} | 23 +++------------- library/alloc/src/lib.rs | 3 +++ library/alloc/tests/btree/mod.rs | 27 ------------------- library/alloc/tests/btree_set_hash.rs | 19 +++++++++++++ library/alloc/tests/lib.rs | 5 +--- 9 files changed, 68 insertions(+), 56 deletions(-) rename library/alloc/{tests/btree/map.rs => src/collections/btree/map/tests.rs} (99%) rename library/alloc/{tests/btree/set.rs => src/collections/btree/set/tests.rs} (98%) delete mode 100644 library/alloc/tests/btree/mod.rs create mode 100644 library/alloc/tests/btree_set_hash.rs diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e7d243bfcb0f7..567bed2fd67e2 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -3024,3 +3024,6 @@ impl> Iterator for MergeIter { } } } + +#[cfg(test)] +mod tests; diff --git a/library/alloc/tests/btree/map.rs b/library/alloc/src/collections/btree/map/tests.rs similarity index 99% rename from library/alloc/tests/btree/map.rs rename to library/alloc/src/collections/btree/map/tests.rs index 5777bd6090714..910e7043092a5 100644 --- a/library/alloc/tests/btree/map.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1,16 +1,20 @@ -use std::collections::btree_map::Entry::{Occupied, Vacant}; -use std::collections::BTreeMap; +use crate::boxed::Box; +use crate::collections::btree_map::Entry::{Occupied, Vacant}; +use crate::collections::BTreeMap; +use crate::fmt::Debug; +use crate::rc::Rc; +use crate::string::String; +use crate::string::ToString; +use crate::vec::Vec; use std::convert::TryFrom; -use std::fmt::Debug; use std::iter::FromIterator; use std::mem; use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::ops::RangeBounds; use std::panic::{catch_unwind, AssertUnwindSafe}; -use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; -use super::DeterministicRng; +use super::super::DeterministicRng; // Value of node::CAPACITY, thus capacity of a tree with a single level, // i.e. a tree who's root is a leaf node at height 0. diff --git a/library/alloc/src/collections/btree/mod.rs b/library/alloc/src/collections/btree/mod.rs index 543ff41a4d48d..6c8a588eb58f3 100644 --- a/library/alloc/src/collections/btree/mod.rs +++ b/library/alloc/src/collections/btree/mod.rs @@ -25,3 +25,30 @@ pub unsafe fn unwrap_unchecked(val: Option) -> T { } }) } + +#[cfg(test)] +/// XorShiftRng +struct DeterministicRng { + x: u32, + y: u32, + z: u32, + w: u32, +} + +#[cfg(test)] +impl DeterministicRng { + fn new() -> Self { + DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } + } + + fn next(&mut self) -> u32 { + let x = self.x; + let t = x ^ (x << 11); + self.x = self.y; + self.y = self.z; + self.z = self.w; + let w_ = self.w; + self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); + self.w + } +} diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 35f4ef1d9b4c7..a559e87e4e298 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1572,3 +1572,6 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Union<'_, T> {} + +#[cfg(test)] +mod tests; diff --git a/library/alloc/tests/btree/set.rs b/library/alloc/src/collections/btree/set/tests.rs similarity index 98% rename from library/alloc/tests/btree/set.rs rename to library/alloc/src/collections/btree/set/tests.rs index b6c34b7c6c346..f4e957e22fe15 100644 --- a/library/alloc/tests/btree/set.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -1,9 +1,10 @@ -use std::collections::BTreeSet; +use crate::collections::BTreeSet; +use crate::vec::Vec; use std::iter::FromIterator; use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::atomic::{AtomicU32, Ordering}; -use super::DeterministicRng; +use super::super::DeterministicRng; #[test] fn test_clone_eq() { @@ -15,24 +16,6 @@ fn test_clone_eq() { assert_eq!(m.clone(), m); } -#[test] -fn test_hash() { - use crate::hash; - - let mut x = BTreeSet::new(); - let mut y = BTreeSet::new(); - - x.insert(1); - x.insert(2); - x.insert(3); - - y.insert(3); - y.insert(2); - y.insert(1); - - assert_eq!(hash(&x), hash(&y)); -} - #[test] fn test_iter_min_max() { let mut a = BTreeSet::new(); diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 75a2c6be41c56..2d25941a52412 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -80,6 +80,7 @@ #![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(btree_drain_filter)] #![feature(cfg_sanitize)] #![feature(cfg_target_has_atomic)] #![feature(coerce_unsized)] @@ -102,6 +103,8 @@ #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(libc)] +#![feature(map_first_last)] +#![feature(map_into_keys_values)] #![feature(negative_impls)] #![feature(new_uninit)] #![feature(nll)] diff --git a/library/alloc/tests/btree/mod.rs b/library/alloc/tests/btree/mod.rs deleted file mode 100644 index 1d08ae13e0540..0000000000000 --- a/library/alloc/tests/btree/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod map; -mod set; - -/// XorShiftRng -struct DeterministicRng { - x: u32, - y: u32, - z: u32, - w: u32, -} - -impl DeterministicRng { - fn new() -> Self { - DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb } - } - - fn next(&mut self) -> u32 { - let x = self.x; - let t = x ^ (x << 11); - self.x = self.y; - self.y = self.z; - self.z = self.w; - let w_ = self.w; - self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8)); - self.w - } -} diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloc/tests/btree_set_hash.rs new file mode 100644 index 0000000000000..e06a95ded94c7 --- /dev/null +++ b/library/alloc/tests/btree_set_hash.rs @@ -0,0 +1,19 @@ +use std::collections::BTreeSet; + +#[test] +fn test_hash() { + use crate::hash; + + let mut x = BTreeSet::new(); + let mut y = BTreeSet::new(); + + x.insert(1); + x.insert(2); + x.insert(3); + + y.insert(3); + y.insert(2); + y.insert(1); + + assert_eq!(hash(&x), hash(&y)); +} diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 3aacd4a687e38..f2ba1ab64810b 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -1,10 +1,7 @@ #![feature(allocator_api)] #![feature(box_syntax)] -#![feature(btree_drain_filter)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] -#![feature(map_first_last)] -#![feature(map_into_keys_values)] #![feature(new_uninit)] #![feature(pattern)] #![feature(str_split_once)] @@ -25,7 +22,7 @@ mod arc; mod binary_heap; mod borrow; mod boxed; -mod btree; +mod btree_set_hash; mod cow_str; mod fmt; mod heap; From 84539eb7b5de1b15467c591dcfb272fefa488bc8 Mon Sep 17 00:00:00 2001 From: Prabakaran Kumaresshan <4676330+nixphix@users.noreply.github.com> Date: Fri, 14 Aug 2020 21:57:42 +0530 Subject: [PATCH 24/29] remove primitive type links --- library/std/src/os/raw/char.md | 2 -- library/std/src/os/raw/double.md | 1 - library/std/src/os/raw/float.md | 1 - library/std/src/os/raw/int.md | 2 -- library/std/src/os/raw/long.md | 2 -- library/std/src/os/raw/longlong.md | 2 -- library/std/src/os/raw/schar.md | 1 - library/std/src/os/raw/short.md | 1 - library/std/src/os/raw/uchar.md | 1 - library/std/src/os/raw/uint.md | 2 -- library/std/src/os/raw/ulong.md | 2 -- library/std/src/os/raw/ulonglong.md | 2 -- library/std/src/os/raw/ushort.md | 1 - 13 files changed, 20 deletions(-) diff --git a/library/std/src/os/raw/char.md b/library/std/src/os/raw/char.md index 9fb0aed89d885..8256b725acfa3 100644 --- a/library/std/src/os/raw/char.md +++ b/library/std/src/os/raw/char.md @@ -7,5 +7,3 @@ C chars are most commonly used to make C strings. Unlike Rust, where the length [C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types [Rust's `char` type]: char [`CStr`]: crate::ffi::CStr -[`i8`]: i8 -[`u8`]: u8 diff --git a/library/std/src/os/raw/double.md b/library/std/src/os/raw/double.md index 51503b5bd69dc..57f4534829ec8 100644 --- a/library/std/src/os/raw/double.md +++ b/library/std/src/os/raw/double.md @@ -4,4 +4,3 @@ This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 [IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754 [`float`]: c_float -[`f64`]: f64 diff --git a/library/std/src/os/raw/float.md b/library/std/src/os/raw/float.md index 7483b97623e7c..61e2abc05189d 100644 --- a/library/std/src/os/raw/float.md +++ b/library/std/src/os/raw/float.md @@ -3,4 +3,3 @@ Equivalent to C's `float` type. This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all. [IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754 -[`f32`]: f32 diff --git a/library/std/src/os/raw/int.md b/library/std/src/os/raw/int.md index 9860e4782f335..8062ff2307a95 100644 --- a/library/std/src/os/raw/int.md +++ b/library/std/src/os/raw/int.md @@ -3,5 +3,3 @@ Equivalent to C's `signed int` (`int`) type. This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example. [`short`]: c_short -[`i32`]: i32 -[`i16`]: i16 diff --git a/library/std/src/os/raw/long.md b/library/std/src/os/raw/long.md index 410100ac64aba..cc160783f78b7 100644 --- a/library/std/src/os/raw/long.md +++ b/library/std/src/os/raw/long.md @@ -3,5 +3,3 @@ Equivalent to C's `signed long` (`long`) type. This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`. [`int`]: c_int -[`i32`]: i32 -[`i64`]: i64 diff --git a/library/std/src/os/raw/longlong.md b/library/std/src/os/raw/longlong.md index 26463dc8ec003..49c61bd61f4ad 100644 --- a/library/std/src/os/raw/longlong.md +++ b/library/std/src/os/raw/longlong.md @@ -3,5 +3,3 @@ Equivalent to C's `signed long long` (`long long`) type. This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type. [`long`]: c_int -[`i64`]: i64 -[`i128`]: i128 diff --git a/library/std/src/os/raw/schar.md b/library/std/src/os/raw/schar.md index cc8d9bf5f42ec..69879c9f17f4d 100644 --- a/library/std/src/os/raw/schar.md +++ b/library/std/src/os/raw/schar.md @@ -3,4 +3,3 @@ Equivalent to C's `signed char` type. This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`]. [`char`]: c_char -[`i8`]: i8 diff --git a/library/std/src/os/raw/short.md b/library/std/src/os/raw/short.md index f2d25e387e2b3..3d1e53d1325f3 100644 --- a/library/std/src/os/raw/short.md +++ b/library/std/src/os/raw/short.md @@ -3,4 +3,3 @@ Equivalent to C's `signed short` (`short`) type. This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example. [`char`]: c_char -[`i16`]: i16 diff --git a/library/std/src/os/raw/uchar.md b/library/std/src/os/raw/uchar.md index 462410820dc6a..b633bb7f8dacf 100644 --- a/library/std/src/os/raw/uchar.md +++ b/library/std/src/os/raw/uchar.md @@ -3,4 +3,3 @@ Equivalent to C's `unsigned char` type. This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`]. [`char`]: c_char -[`u8`]: u8 diff --git a/library/std/src/os/raw/uint.md b/library/std/src/os/raw/uint.md index 4a5c4ab1d4893..f3abea35937ab 100644 --- a/library/std/src/os/raw/uint.md +++ b/library/std/src/os/raw/uint.md @@ -3,5 +3,3 @@ Equivalent to C's `unsigned int` type. This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example. [`int`]: c_int -[`u32`]: u32 -[`u16`]: u16 diff --git a/library/std/src/os/raw/ulong.md b/library/std/src/os/raw/ulong.md index 745759c51abdc..4ab304e657773 100644 --- a/library/std/src/os/raw/ulong.md +++ b/library/std/src/os/raw/ulong.md @@ -3,5 +3,3 @@ Equivalent to C's `unsigned long` type. This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`. [`long`]: c_long -[`u32`]: u32 -[`u64`]: u64 diff --git a/library/std/src/os/raw/ulonglong.md b/library/std/src/os/raw/ulonglong.md index 981106b23b6a4..a27d70e17537d 100644 --- a/library/std/src/os/raw/ulonglong.md +++ b/library/std/src/os/raw/ulonglong.md @@ -3,5 +3,3 @@ Equivalent to C's `unsigned long long` type. This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type. [`long long`]: c_longlong -[`u64`]: u64 -[`u128`]: u128 diff --git a/library/std/src/os/raw/ushort.md b/library/std/src/os/raw/ushort.md index 6e2506d52cf84..6928e51b352c8 100644 --- a/library/std/src/os/raw/ushort.md +++ b/library/std/src/os/raw/ushort.md @@ -3,4 +3,3 @@ Equivalent to C's `unsigned short` type. This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`]. [`short`]: c_short -[`u16`]: u16 From ee4f893e27a6270cd84dcc4a27884d76722cc0fd Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Fri, 14 Aug 2020 19:08:09 +0200 Subject: [PATCH 25/29] Apply suggestions from code review Co-authored-by: Joshua Nelson --- library/std/src/ffi/c_str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 194573da76736..51bc8c1c41599 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -329,7 +329,7 @@ impl FromVecWithNulError { /// [`CString::into_string`] performs UTF-8 validation on those bytes and may /// return this error. /// -/// This `struct` is created by the [`CString::into_string`] method. See +/// This `struct` is created by [`CString::into_string()`]. See /// its documentation for more. #[derive(Clone, PartialEq, Eq, Debug)] #[stable(feature = "cstring_into", since = "1.7.0")] @@ -566,7 +566,7 @@ impl CString { vec } - /// Equivalent to the [`CString::into_bytes`] function except that the + /// Equivalent to [`CString::into_bytes()`] except that the /// returned vector includes the trailing nul terminator. /// /// # Examples @@ -605,7 +605,7 @@ impl CString { &self.inner[..self.inner.len() - 1] } - /// Equivalent to the [`CString::as_bytes`] function except that the + /// Equivalent to [`CString::as_bytes()`] except that the /// returned slice includes the trailing nul terminator. /// /// # Examples From 4ecdec1fb665363ee46af24a9a6edf73a9b602ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 14 Aug 2020 10:16:34 -0700 Subject: [PATCH 26/29] review comment: suggestion message wording --- src/librustc_resolve/late/diagnostics.rs | 3 ++- src/test/ui/issues/issue-5099.stderr | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 67a9d9b4ec1b4..3df6a230b0f09 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -202,7 +202,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { }; err.span_suggestion_verbose( span, - "you are also missing a `self` receiver argument", + "if you meant to use `self`, you are also missing a `self` receiver \ + argument", sugg.to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/issues/issue-5099.stderr b/src/test/ui/issues/issue-5099.stderr index 56b02c45a08d7..b52fd28b2b575 100644 --- a/src/test/ui/issues/issue-5099.stderr +++ b/src/test/ui/issues/issue-5099.stderr @@ -8,7 +8,7 @@ help: you might have meant to use `self` here instead | LL | self.a | ^^^^ -help: you are also missing a `self` receiver argument +help: if you meant to use `self`, you are also missing a `self` receiver argument | LL | fn a(&self) -> A { | ^^^^^ @@ -23,7 +23,7 @@ help: you might have meant to use `self` here instead | LL | self.b(x); | ^^^^ -help: you are also missing a `self` receiver argument +help: if you meant to use `self`, you are also missing a `self` receiver argument | LL | fn b(&self, x: i32) { | ^^^^^^ From e97fa1e3da60376cacb73a37d3f486bcccac9571 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 14 Aug 2020 19:33:04 +0200 Subject: [PATCH 27/29] libstd/ffi/c_str.rs: #![deny(unsafe_op_in_unsafe_fn)], enclose unsafe operations in unsafe blocks --- library/std/src/ffi/c_str.rs | 39 +++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index da25a0ede729d..8816262668761 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -1,3 +1,4 @@ +#![deny(unsafe_op_in_unsafe_fn)] use crate::ascii; use crate::borrow::{Borrow, Cow}; use crate::cmp::Ordering; @@ -510,9 +511,16 @@ impl CString { /// ``` #[stable(feature = "cstr_memory", since = "1.4.0")] pub unsafe fn from_raw(ptr: *mut c_char) -> CString { - let len = sys::strlen(ptr) + 1; // Including the NUL byte - let slice = slice::from_raw_parts_mut(ptr, len as usize); - CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } + // SAFETY: This is called with a pointer that was obtained from a call + // to `CString::into_raw` and the length has not been modified. As such, + // we know there is a NUL byte (and only one) at the end and that the + // information about the size of the allocation is correct on Rust's + // side. + unsafe { + let len = sys::strlen(ptr) + 1; // Including the NUL byte + let slice = slice::from_raw_parts_mut(ptr, len as usize); + CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } + } } /// Consumes the `CString` and transfers ownership of the string to a C caller. @@ -1228,9 +1236,21 @@ impl CStr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { - let len = sys::strlen(ptr); - let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + // SAFETY: The caller has provided a pointer that points to a valid C + // string with a NUL terminator of size less than `isize::MAX`, whose + // content remain valid and doesn't change for the lifetime of the + // returned `CStr`. + // + // Thus computing the length is fine (a NUL byte exists), the call to + // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning + // the call to `from_bytes_with_nul_unchecked` is correct. + // + // The cast from c_char to u8 is ok because a c_char is always one byte. + unsafe { + let len = sys::strlen(ptr); + let ptr = ptr as *const u8; + CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + } } /// Creates a C string wrapper from a byte slice. @@ -1299,7 +1319,12 @@ impl CStr { #[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { - &*(bytes as *const [u8] as *const CStr) + // SAFETY: Casting to CStr is safe because its internal representation + // is a [u8] too (safe only inside std). + // Dereferencing the obtained pointer is safe because it comes from a + // reference. Making a reference is then safe because its lifetime + // is bound by the lifetime of the given `bytes`. + unsafe { &*(bytes as *const [u8] as *const CStr) } } /// Returns the inner pointer to this C string. From 61866bc60cab64677c710dd7146c35b0ecdb40cc Mon Sep 17 00:00:00 2001 From: chansuke Date: Thu, 6 Aug 2020 18:19:31 +0900 Subject: [PATCH 28/29] Use intra-doc links in `mem::manually_drop` & `mem::maybe_uninit` --- library/core/src/mem/manually_drop.rs | 12 ++++-------- library/core/src/mem/maybe_uninit.rs | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 920f5e9c0bd28..e45aa86c0795a 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -56,9 +56,9 @@ use crate::ptr; /// working with [pinned] data, where reusing the memory without calling the destructor could lead /// to Undefined Behaviour. /// -/// [`mem::zeroed`]: fn.zeroed.html -/// [`MaybeUninit`]: union.MaybeUninit.html -/// [pinned]: ../pin/index.html +/// [`mem::zeroed`]: crate::mem::zeroed +/// [`MaybeUninit`]: crate::mem::MaybeUninit +/// [pinned]: crate::pin #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -116,8 +116,6 @@ impl ManuallyDrop { /// leaving the state of this container unchanged. /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. /// - /// [`ManuallyDrop::drop`]: #method.drop - /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] @@ -148,9 +146,7 @@ impl ManuallyDrop { /// This is normally prevented by the type system, but users of `ManuallyDrop` must /// uphold those guarantees without assistance from the compiler. /// - /// [`ManuallyDrop::into_inner`]: #method.into_inner - /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html - /// [pinned]: ../pin/index.html + /// [pinned]: crate::pin #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop) { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 027498d3911c8..d2d65fd2fa517 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -247,7 +247,7 @@ impl MaybeUninit { /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. /// - /// [`assume_init`]: #method.assume_init + /// [`assume_init`]: MaybeUninit::assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] #[inline(always)] @@ -525,7 +525,7 @@ impl MaybeUninit { /// to ensure that that data may indeed be duplicated. /// /// [inv]: #initialization-invariant - /// [`assume_init`]: #method.assume_init + /// [`assume_init`]: MaybeUninit::assume_init /// /// # Examples /// From 0e610bb31e885bf79fae44c3c1b665f12bb87ec4 Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Fri, 14 Aug 2020 22:52:23 +0200 Subject: [PATCH 29/29] Document the unsafe keyword --- library/std/src/keyword_docs.rs | 184 +++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 3 deletions(-) diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index ff343625a19ed..c39989a60c92b 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -1813,12 +1813,190 @@ mod type_keyword {} #[doc(keyword = "unsafe")] // -/// Code or interfaces whose [memory safety] cannot be verified by the type system. +/// Code or interfaces whose [memory safety] cannot be verified by the type +/// system. +/// +/// The `unsafe` keyword has two uses: to declare the existence of contracts the +/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a +/// programmer has checked that these contracts have been upheld (`unsafe {}` +/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually +/// exclusive, as can be seen in `unsafe fn`. +/// +/// # Unsafe abilities +/// +/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is +/// referred to as [soundness]: a well-typed program actually has the desired +/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation +/// on the subject. +/// +/// To ensure soundness, Safe Rust is restricted enough that it can be +/// automatically checked. Sometimes, however, it is necessary to write code +/// that is correct for reasons which are too clever for the compiler to +/// understand. In those cases, you need to use Unsafe Rust. +/// +/// Here are the abilities Unsafe Rust has in addition to Safe Rust: +/// +/// - Dereference [raw pointers] +/// - Implement `unsafe` [`trait`]s +/// - Call `unsafe` functions +/// - Mutate [`static`]s (including [`extern`]al ones) +/// - Access fields of [`union`]s +/// +/// However, this extra power comes with extra responsibilities: it is now up to +/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the +/// pieces of code that need to worry about this. +/// +/// ## The different meanings of `unsafe` +/// +/// Not all uses of `unsafe` are equivalent: some are here to mark the existence +/// of a contract the programmer must check, others are to say "I have checked +/// the contract, go ahead and do this". The following +/// [discussion on Rust Internals] has more in-depth explanations about this but +/// here is a summary of the main points: +/// +/// - `unsafe fn`: calling this function means abiding by a contract the +/// compiler cannot enforce. +/// - `unsafe trait`: implementing the [`trait`] means abiding by a +/// contract the compiler cannot enforce. +/// - `unsafe {}`: the contract necessary to call the operations inside the +/// block has been checked by the programmer and is guaranteed to be respected. +/// - `unsafe impl`: the contract necessary to implement the trait has been +/// checked by the programmer and is guaranteed to be respected. +/// +/// `unsafe fn` also acts like an `unsafe {}` block +/// around the code inside the function. This means it is not just a signal to +/// the caller, but also promises that the preconditions for the operations +/// inside the function are upheld. Mixing these two meanings can be confusing +/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when +/// making `unsafe` operations. +/// +/// See the [Rustnomicon] and the [Reference] for more informations. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// # Examples +/// +/// ## Marking elements as `unsafe` +/// +/// `unsafe` can be used on functions. Note that functions and statics declared +/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions +/// declared as `extern "something" fn ...`). Mutable statics are always unsafe, +/// wherever they are declared. Methods can also be declared as `unsafe`: +/// +/// ```rust +/// # #![allow(dead_code)] +/// static mut FOO: &str = "hello"; +/// +/// unsafe fn unsafe_fn() {} +/// +/// extern "C" { +/// fn unsafe_extern_fn(); +/// static BAR: *mut u32; +/// } +/// +/// trait SafeTraitWithUnsafeMethod { +/// unsafe fn unsafe_method(&self); +/// } +/// +/// struct S; +/// +/// impl S { +/// unsafe fn unsafe_method_on_struct() {} +/// } +/// ``` +/// +/// Traits can also be declared as `unsafe`: +/// +/// ```rust +/// unsafe trait UnsafeTrait {} +/// ``` /// +/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety +/// contract that the compiler cannot enforce, documenting it is important. The +/// standard library has many examples of this, like the following which is an +/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract +/// that must be fulfilled to safely call the function. +/// +/// ```rust,ignore (stub-to-show-doc-example) +/// /// Forces the length of the vector to `new_len`. +/// /// +/// /// This is a low-level operation that maintains none of the normal +/// /// invariants of the type. Normally changing the length of a vector +/// /// is done using one of the safe operations instead, such as +/// /// `truncate`, `resize`, `extend`, or `clear`. +/// /// +/// /// # Safety +/// /// +/// /// - `new_len` must be less than or equal to `capacity()`. +/// /// - The elements at `old_len..new_len` must be initialized. +/// pub unsafe fn set_len(&mut self, new_len: usize) +/// ``` +/// +/// ## Using `unsafe {}` blocks and `impl`s +/// +/// Performing `unsafe` operations requires an `unsafe {}` block: +/// +/// ```rust +/// # #![allow(dead_code)] +/// /// Dereference the given pointer. +/// /// +/// /// # Safety +/// /// +/// /// `ptr` must be aligned and must not be dangling. +/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 { +/// *ptr +/// } +/// +/// let a = 3; +/// let b = &a as *const _; +/// // SAFETY: `a` has not been dropped and references are always aligned, +/// // so `b` is a valid address. +/// unsafe { assert_eq!(*b, deref_unchecked(b)); }; +/// ``` +/// +/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This +/// makes a guarantee to other `unsafe` code that the implementation satisfies +/// the trait's safety contract. The [Send] and [Sync] traits are examples of +/// this behaviour in the standard library. +/// +/// ```rust +/// /// Implementors of this trait must guarantee an element is always +/// /// accessible with index 3. +/// unsafe trait ThreeIndexable { +/// /// Returns a reference to the element with index 3 in `&self`. +/// fn three(&self) -> &T; +/// } +/// +/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe` +/// // because the implementor must abide by a contract the compiler cannot +/// // check but as a programmer we know there will always be a valid element +/// // at index 3 to access. +/// unsafe impl ThreeIndexable for [T; 4] { +/// fn three(&self) -> &T { +/// // SAFETY: implementing the trait means there always is an element +/// // with index 3 accessible. +/// unsafe { self.get_unchecked(3) } +/// } +/// } +/// +/// let a = [1, 2, 4, 8]; +/// assert_eq!(a.three(), &8); +/// ``` +/// +/// [`extern`]: keyword.extern.html +/// [`trait`]: keyword.trait.html +/// [`static`]: keyword.static.html +/// [`union`]: keyword.union.html +/// [`impl`]: keyword.impl.html +/// [Send]: marker/trait.Send.html +/// [Sync]: marker/trait.Sync.html +/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len +/// [raw pointers]: ../reference/types/pointer.html /// [memory safety]: ../book/ch19-01-unsafe-rust.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 +/// [Rustnomicon]: ../nomicon/index.html +/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html +/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library +/// [Reference]: ../reference/unsafety.html +/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585 +/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696 mod unsafe_keyword {} #[doc(keyword = "use")]