From 875e01e6166d4b5dea370023564703968a3cd92a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 22 Nov 2021 02:08:59 -0800 Subject: [PATCH 1/7] Add `<*{const|mut} T>::{to|from}_bits` Named based on the floating-point methods of the same name, as those are also about returning the *representation* of the value. --- library/core/src/ptr/const_ptr.rs | 48 ++++++++++++++++++++++++++++++ library/core/src/ptr/mut_ptr.rs | 49 +++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 344b483662abd..03f17e0697cdb 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -48,6 +48,54 @@ impl *const T { self as _ } + /// Casts a pointer to its raw bits. + /// + /// This is equivalent to `as usize`, but is more specific to enhance readability. + /// The inverse method is [`Self::from_bits`]. + /// + /// In particular, `*p as usize` and `p as usize` will both compile for + /// pointers to numeric types but do very different things, so using this + /// helps emphasize that reading the bits was intentional. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// let array = [13, 42]; + /// let p0: *const i32 = &array[0]; + /// assert_eq!(<*const _>::from_bits(p0.to_bits()), p0); + /// let p1: *const i32 = &array[1]; + /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn to_bits(self) -> usize + where + T: Sized, + { + self as usize + } + + /// Creates a pointer from its raw bits. + /// + /// This is equivalent to `as *const T`, but is more specific to enhance readability. + /// The inverse method is [`Self::to_bits`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::ptr::NonNull; + /// let dangling: *const u8 = NonNull::dangling().as_ptr(); + /// assert_eq!(<*const u8>::from_bits(1), dangling); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn from_bits(bits: usize) -> Self + where + T: Sized, + { + bits as Self + } + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts`]. diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index f3b2bdfefe5df..5a5ce5ee121ae 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -47,6 +47,55 @@ impl *mut T { self as _ } + /// Casts a pointer to its raw bits. + /// + /// This is equivalent to `as usize`, but is more specific to enhance readability. + /// The inverse method is [`Self::from_bits`]. + /// + /// In particular, `*p as usize` and `p as usize` will both compile for + /// pointers to numeric types but do very different things, so using this + /// helps emphasize that reading the bits was intentional. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// let mut array = [13, 42]; + /// let mut it = array.iter_mut(); + /// let p0: *mut i32 = it.next().unwrap(); + /// assert_eq!(<*mut _>::from_bits(p0.to_bits()), p0); + /// let p1: *mut i32 = it.next().unwrap(); + /// assert_eq!(p1.to_bits() - p0.to_bits(), 4); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn to_bits(self) -> usize + where + T: Sized, + { + self as usize + } + + /// Creates a pointer from its raw bits. + /// + /// This is equivalent to `as *mut T`, but is more specific to enhance readability. + /// The inverse method is [`Self::to_bits`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ptr_to_from_bits)] + /// use std::ptr::NonNull; + /// let dangling: *mut u8 = NonNull::dangling().as_ptr(); + /// assert_eq!(<*mut u8>::from_bits(1), dangling); + /// ``` + #[unstable(feature = "ptr_to_from_bits", issue = "91126")] + pub fn from_bits(bits: usize) -> Self + where + T: Sized, + { + bits as Self + } + /// Decompose a (possibly wide) pointer into its address and metadata components. /// /// The pointer can be later reconstructed with [`from_raw_parts_mut`]. From 348a25044b6f263a61cd41cd3767c3d8d1e8da74 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 22 Nov 2021 02:40:56 -0800 Subject: [PATCH 2/7] Intra-doc links apparently don't like pointers? --- library/core/src/ptr/const_ptr.rs | 4 ++-- library/core/src/ptr/mut_ptr.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index 03f17e0697cdb..3c716672113e5 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -51,7 +51,7 @@ impl *const T { /// Casts a pointer to its raw bits. /// /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`Self::from_bits`]. + /// The inverse method is [`from_bits`](#method.from_bits). /// /// In particular, `*p as usize` and `p as usize` will both compile for /// pointers to numeric types but do very different things, so using this @@ -78,7 +78,7 @@ impl *const T { /// Creates a pointer from its raw bits. /// /// This is equivalent to `as *const T`, but is more specific to enhance readability. - /// The inverse method is [`Self::to_bits`]. + /// The inverse method is [`to_bits`](#method.to_bits). /// /// # Examples /// diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 5a5ce5ee121ae..5d4e37641ee84 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -50,7 +50,7 @@ impl *mut T { /// Casts a pointer to its raw bits. /// /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`Self::from_bits`]. + /// The inverse method is [`from_bits`](#method.from_bits-1). /// /// In particular, `*p as usize` and `p as usize` will both compile for /// pointers to numeric types but do very different things, so using this @@ -78,7 +78,7 @@ impl *mut T { /// Creates a pointer from its raw bits. /// /// This is equivalent to `as *mut T`, but is more specific to enhance readability. - /// The inverse method is [`Self::to_bits`]. + /// The inverse method is [`to_bits`](#method.to_bits-1). /// /// # Examples /// From 03be3e21b1e259b24859b8f00f5280e56bd0b254 Mon Sep 17 00:00:00 2001 From: hi-rustin Date: Sun, 28 Nov 2021 15:12:56 +0800 Subject: [PATCH 3/7] Add --out-dir flag for rustdoc Signed-off-by: hi-rustin --- src/doc/rustdoc/src/command-line-arguments.md | 4 ++-- src/librustdoc/config.rs | 14 ++++++++++++-- src/librustdoc/lib.rs | 11 ++++++++++- .../run-make/rustdoc-with-out-dir-option/Makefile | 8 ++++++++ .../rustdoc-with-out-dir-option/src/lib.rs | 2 ++ .../run-make/rustdoc-with-output-option/Makefile | 8 ++++++++ .../run-make/rustdoc-with-output-option/src/lib.rs | 2 ++ .../rustdoc-with-short-out-dir-option/Makefile | 8 ++++++++ .../rustdoc-with-short-out-dir-option/src/lib.rs | 2 ++ .../use_both_out_dir_and_output_options.rs | 1 + .../use_both_out_dir_and_output_options.stderr | 2 ++ 11 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 src/test/run-make/rustdoc-with-out-dir-option/Makefile create mode 100644 src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs create mode 100644 src/test/run-make/rustdoc-with-output-option/Makefile create mode 100644 src/test/run-make/rustdoc-with-output-option/src/lib.rs create mode 100644 src/test/run-make/rustdoc-with-short-out-dir-option/Makefile create mode 100644 src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs create mode 100644 src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs create mode 100644 src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index d694862266254..9de2e733de7c7 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -57,13 +57,13 @@ release: 1.17.0 LLVM version: 3.9 ``` -## `-o`/`--output`: output path +## `-o`/`--out-dir`: output directory path Using this flag looks like this: ```bash $ rustdoc src/lib.rs -o target/doc -$ rustdoc src/lib.rs --output target/doc +$ rustdoc src/lib.rs --out-dir target/doc ``` By default, `rustdoc`'s output appears in a directory named `doc` in diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 04bcade156a9d..ee19567be102f 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -504,8 +504,18 @@ impl Options { return Err(1); } - let output = - matches.opt_str("o").map(|s| PathBuf::from(&s)).unwrap_or_else(|| PathBuf::from("doc")); + let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); + let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); + let output = match (out_dir, output) { + (Some(_), Some(_)) => { + diag.struct_err("cannot use both 'out-dir' and 'output' at once").emit(); + return Err(1); + } + (Some(out_dir), None) => out_dir, + (None, Some(output)) => output, + (None, None) => PathBuf::from("doc"), + }; + let cfgs = matches.opt_strs("cfg"); let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s)); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b6311abb5c3e8..8699ab20b19d4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -278,7 +278,16 @@ fn opts() -> Vec { o.optopt("r", "input-format", "the input type of the specified file", "[rust]") }), stable("w", |o| o.optopt("w", "output-format", "the output type to write", "[html]")), - stable("o", |o| o.optopt("o", "output", "where to place the output", "PATH")), + stable("output", |o| { + o.optopt( + "", + "output", + "Which directory to place the output. \ + This option is deprecated, use --out-dir instead.", + "PATH", + ) + }), + stable("o", |o| o.optopt("o", "out-dir", "which directory to place the output", "PATH")), stable("crate-name", |o| { o.optopt("", "crate-name", "specify the name of this crate", "NAME") }), diff --git a/src/test/run-make/rustdoc-with-out-dir-option/Makefile b/src/test/run-make/rustdoc-with-out-dir-option/Makefile new file mode 100644 index 0000000000000..f79fce8eeeae1 --- /dev/null +++ b/src/test/run-make/rustdoc-with-out-dir-option/Makefile @@ -0,0 +1,8 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" + +all: + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs b/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs new file mode 100644 index 0000000000000..044bb6acb19b8 --- /dev/null +++ b/src/test/run-make/rustdoc-with-out-dir-option/src/lib.rs @@ -0,0 +1,2 @@ +// @has foobar/fn.ok.html +pub fn ok() {} diff --git a/src/test/run-make/rustdoc-with-output-option/Makefile b/src/test/run-make/rustdoc-with-output-option/Makefile new file mode 100644 index 0000000000000..654f9672588ed --- /dev/null +++ b/src/test/run-make/rustdoc-with-output-option/Makefile @@ -0,0 +1,8 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" + +all: + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make/rustdoc-with-output-option/src/lib.rs b/src/test/run-make/rustdoc-with-output-option/src/lib.rs new file mode 100644 index 0000000000000..044bb6acb19b8 --- /dev/null +++ b/src/test/run-make/rustdoc-with-output-option/src/lib.rs @@ -0,0 +1,2 @@ +// @has foobar/fn.ok.html +pub fn ok() {} diff --git a/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile b/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile new file mode 100644 index 0000000000000..1e9ba71de2649 --- /dev/null +++ b/src/test/run-make/rustdoc-with-short-out-dir-option/Makefile @@ -0,0 +1,8 @@ +-include ../../run-make-fulldeps/tools.mk + +OUTPUT_DIR := "$(TMPDIR)/rustdoc" + +all: + $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib -o $(OUTPUT_DIR) + + $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs b/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs new file mode 100644 index 0000000000000..044bb6acb19b8 --- /dev/null +++ b/src/test/run-make/rustdoc-with-short-out-dir-option/src/lib.rs @@ -0,0 +1,2 @@ +// @has foobar/fn.ok.html +pub fn ok() {} diff --git a/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs new file mode 100644 index 0000000000000..5037043f19ade --- /dev/null +++ b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.rs @@ -0,0 +1 @@ +// compile-flags: --output ./foo diff --git a/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr new file mode 100644 index 0000000000000..96d2295ac3e44 --- /dev/null +++ b/src/test/rustdoc-ui/use_both_out_dir_and_output_options.stderr @@ -0,0 +1,2 @@ +error: cannot use both 'out-dir' and 'output' at once + From e68887e67cc6b7bb4ea5113a40eaa4c0831bda13 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 5 Dec 2021 13:36:06 +0000 Subject: [PATCH 4/7] socket ancillary data implementation for dragonflybsd. --- library/std/src/os/unix/net/ancillary.rs | 82 +++++++++++++++++++++++- library/std/src/os/unix/net/datagram.rs | 14 ++-- library/std/src/sys/unix/net.rs | 4 +- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 6e6f5212b4651..a29008140f784 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -16,6 +16,8 @@ mod libc { pub use libc::c_int; pub struct ucred; pub struct cmsghdr; + #[cfg(target_os = "dragonfly")] + pub struct cmsgcred; pub type pid_t = i32; pub type gid_t = u32; pub type uid_t = u32; @@ -183,6 +185,11 @@ impl<'a, T> Iterator for AncillaryDataIter<'a, T> { #[derive(Clone)] pub struct SocketCred(libc::ucred); +#[cfg(target_os = "dragonfly")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +#[derive(Clone)] +pub struct SocketCred(libc::cmsgcred); + #[cfg(any(doc, target_os = "android", target_os = "linux",))] impl SocketCred { /// Create a Unix credential struct. @@ -234,6 +241,57 @@ impl SocketCred { } } +#[cfg(target_os = "dragonfly")] +impl SocketCred { + /// Create a Unix credential struct. + /// + /// PID, UID and GID is set to 0. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + #[must_use] + pub fn new() -> SocketCred { + SocketCred(libc::cmsgcred { cmsgcred_pid: 0, cmsgcred_uid: 0, cmsgcred_gid: 0 }) + } + + /// Set the PID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_pid(&mut self, pid: libc::pid_t) { + self.0.cmsgcred_pid = pid; + } + + /// Get the current PID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_pid(&self) -> libc::pid_t { + self.0.cmsgcred_pid + } + + /// Set the UID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_uid(&mut self, uid: libc::uid_t) { + self.0.cmsgcred_uid = uid; + } + + /// Get the current UID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_uid(&self) -> libc::uid_t { + self.0.cmsgcred_uid + } + + /// Set the GID. + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn set_gid(&mut self, gid: libc::gid_t) { + self.0.cmsgcred_gid = gid; + } + + /// Get the current GID. + #[must_use] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn get_gid(&self) -> libc::gid_t { + self.0.cmsgcred_gid + } +} + /// This control message contains file descriptors. /// /// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`. @@ -256,7 +314,11 @@ impl<'a> Iterator for ScmRights<'a> { #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>); -#[cfg(any(doc, target_os = "android", target_os = "linux",))] +#[cfg(target_os = "dragonfly")] +#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] +pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::cmsgcred>); + +#[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] impl<'a> Iterator for ScmCredentials<'a> { type Item = SocketCred; @@ -300,7 +362,7 @@ impl<'a> AncillaryData<'a> { /// # Safety /// /// `data` must contain a valid control message and the control message must be type of - /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDENTIALS`. + /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDS`. #[cfg(any(doc, target_os = "android", target_os = "linux",))] unsafe fn as_credentials(data: &'a [u8]) -> Self { let ancillary_data_iter = AncillaryDataIter::new(data); @@ -320,6 +382,9 @@ impl<'a> AncillaryData<'a> { libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)), #[cfg(any(target_os = "android", target_os = "linux",))] libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)), + #[cfg(target_os = "dragonfly")] + libc::SCM_CREDS => Ok(AncillaryData::as_credentials(data)), + cmsg_type => { Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type }) } @@ -544,6 +609,19 @@ impl<'a> SocketAncillary<'a> { ) } + #[cfg(target_os = "dragonfly")] + #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] + pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool { + self.truncated = false; + add_to_ancillary_data( + &mut self.buffer, + &mut self.length, + creds, + libc::SOL_SOCKET, + libc::SCM_CREDS, + ) + } + /// Clears the ancillary data, removing all values. /// /// # Example diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index a2caccc784917..f23f8f94a242f 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -854,8 +854,14 @@ impl UnixDatagram { /// /// # Examples /// - #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")] - #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")] + #[cfg_attr( + any(target_os = "android", target_os = "linux", target_os = "dragonfly"), + doc = "```no_run" + )] + #[cfg_attr( + not(any(target_os = "android", target_os = "linux", target_os = "dragonfly")), + doc = "```ignore" + )] /// #![feature(unix_socket_ancillary_data)] /// use std::os::unix::net::UnixDatagram; /// @@ -865,7 +871,7 @@ impl UnixDatagram { /// Ok(()) /// } /// ``` - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { self.0.set_passcred(passcred) @@ -877,7 +883,7 @@ impl UnixDatagram { /// Get the socket option `SO_PASSCRED`. /// /// [`set_passcred`]: UnixDatagram::set_passcred - #[cfg(any(doc, target_os = "android", target_os = "linux",))] + #[cfg(any(doc, target_os = "android", target_os = "linux", target_os = "dragonfly",))] #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")] pub fn passcred(&self) -> io::Result { self.0.passcred() diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index a82a0172126d4..15d0dbe07fe7e 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -408,12 +408,12 @@ impl Socket { Ok(raw != 0) } - #[cfg(any(target_os = "android", target_os = "linux",))] + #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] pub fn set_passcred(&self, passcred: bool) -> io::Result<()> { setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int) } - #[cfg(any(target_os = "android", target_os = "linux",))] + #[cfg(any(target_os = "android", target_os = "linux", target_os = "dragonfly",))] pub fn passcred(&self) -> io::Result { let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?; Ok(passcred != 0) From acd39ff0feb91a2f119e30710af0e0c021599fe1 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Wed, 1 Dec 2021 17:57:09 +0000 Subject: [PATCH 5/7] Make IdFunctor::try_map_id panic-safe --- compiler/rustc_data_structures/src/functor.rs | 53 ++++++++++--------- compiler/rustc_data_structures/src/lib.rs | 1 + 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 71ff762c714bf..a3d3f988344c6 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -34,38 +34,43 @@ impl IdFunctor for Vec { type Inner = T; #[inline] - fn try_map_id(mut self, mut f: F) -> Result + fn try_map_id(self, mut f: F) -> Result where F: FnMut(Self::Inner) -> Result, { - // FIXME: We don't really care about panics here and leak - // far more than we should, but that should be fine for now. - let len = self.len(); - unsafe { - self.set_len(0); - let start = self.as_mut_ptr(); - for i in 0..len { - let p = start.add(i); - match f(p.read()) { - Ok(val) => p.write(val), - Err(err) => { - // drop all other elements in self - // (current element was "moved" into the call to f) - for j in (0..i).chain(i + 1..len) { - start.add(j).drop_in_place(); - } + struct HoleVec { + vec: Vec>, + hole: Option, + } - // returning will drop self, releasing the allocation - // (len is 0 so elements will not be re-dropped) - return Err(err); + impl Drop for HoleVec { + fn drop(&mut self) { + unsafe { + for (index, slot) in self.vec.iter_mut().enumerate() { + if self.hole != Some(index) { + mem::ManuallyDrop::drop(slot); + } } } } - // Even if we encountered an error, set the len back - // so we don't leak memory. - self.set_len(len); } - Ok(self) + + unsafe { + let (ptr, length, capacity) = self.into_raw_parts(); + let vec = Vec::from_raw_parts(ptr.cast(), length, capacity); + let mut hole_vec = HoleVec { vec, hole: None }; + + for (index, slot) in hole_vec.vec.iter_mut().enumerate() { + hole_vec.hole = Some(index); + let original = mem::ManuallyDrop::take(slot); + let mapped = f(original)?; + *slot = mem::ManuallyDrop::new(mapped); + hole_vec.hole = None; + } + + mem::forget(hole_vec); + Ok(Vec::from_raw_parts(ptr, length, capacity)) + } } } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index e17724b72f8b8..181e5180d53d5 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -23,6 +23,7 @@ #![feature(once_cell)] #![feature(test)] #![feature(thread_id_value)] +#![feature(vec_into_raw_parts)] #![allow(rustc::default_hash_types)] #![deny(unaligned_references)] From ea68758299a89556e67f0bfffffb19c0c8346e8a Mon Sep 17 00:00:00 2001 From: David Koloski Date: Fri, 3 Dec 2021 15:32:51 +0000 Subject: [PATCH 6/7] Add needs-unwind to tests that depend on panicking This directive isn't automatically set by compiletest or x.py, but can be turned on manually for targets that require it. --- src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs | 1 + src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs | 1 + src/test/ui/array-slice-vec/nested-vec-3.rs | 1 + src/test/ui/array-slice-vec/slice-panic-1.rs | 1 + src/test/ui/array-slice-vec/slice-panic-2.rs | 1 + .../issue-65419/issue-65419-async-fn-resume-after-panic.rs | 1 + src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs | 1 + src/test/ui/builtin-clone-unwind.rs | 1 + src/test/ui/catch-unwind-bang.rs | 1 + src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs | 1 + .../2229_closure_analysis/migrations/mir_calls_to_shims.fixed | 1 + .../2229_closure_analysis/migrations/mir_calls_to_shims.rs | 1 + .../migrations/mir_calls_to_shims.stderr | 4 ++-- src/test/ui/drop/drop-trait-enum.rs | 1 + src/test/ui/drop/dynamic-drop-async.rs | 1 + src/test/ui/drop/dynamic-drop.rs | 1 + src/test/ui/drop/terminate-in-initializer.rs | 1 + .../issue-64655-allow-unwind-when-calling-panic-directly.rs | 1 + .../ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 1 + src/test/ui/generator/generator-resume-after-panic.rs | 1 + src/test/ui/generator/panic-drops-resume.rs | 1 + src/test/ui/generator/panic-drops.rs | 1 + src/test/ui/generator/panic-safe.rs | 1 + src/test/ui/generator/resume-after-return.rs | 1 + src/test/ui/intrinsics/panic-uninitialized-zeroed.rs | 1 + src/test/ui/issues/issue-14875.rs | 1 + src/test/ui/issues/issue-25089.rs | 1 + src/test/ui/issues/issue-26655.rs | 1 + src/test/ui/issues/issue-29485.rs | 1 + src/test/ui/issues/issue-29948.rs | 1 + src/test/ui/issues/issue-30018-panic.rs | 1 + src/test/ui/issues/issue-43853.rs | 1 + src/test/ui/issues/issue-46519.rs | 1 + src/test/ui/iterators/iter-count-overflow-debug.rs | 1 + src/test/ui/iterators/iter-position-overflow-debug.rs | 1 + src/test/ui/iterators/iter-step-overflow-debug.rs | 1 + src/test/ui/iterators/iter-sum-overflow-debug.rs | 1 + src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs | 1 + src/test/ui/macros/macro-comma-behavior-rpass.rs | 1 + src/test/ui/mir/mir_calls_to_shims.rs | 1 + src/test/ui/mir/mir_drop_order.rs | 1 + src/test/ui/mir/mir_drop_panics.rs | 1 + src/test/ui/mir/mir_dynamic_drops_3.rs | 1 + src/test/ui/numbers-arithmetic/int-abs-overflow.rs | 1 + .../ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs | 1 + src/test/ui/panics/panic-handler-chain.rs | 1 + src/test/ui/panics/panic-handler-flail-wildly.rs | 1 + src/test/ui/panics/panic-handler-set-twice.rs | 1 + src/test/ui/panics/panic-in-dtor-drops-fields.rs | 1 + src/test/ui/panics/panic-recover-propagate.rs | 1 + src/test/ui/privacy/reachable-unnameable-items.rs | 1 + src/test/ui/proc-macro/expand-with-a-macro.rs | 1 + .../rfc-1937-termination-trait/termination-trait-in-test.rs | 1 + src/test/ui/rfc-2091-track-caller/std-panic-locations.rs | 1 + src/test/ui/rfcs/rfc1857-drop-order.rs | 1 + src/test/ui/runtime/rt-explody-panic-payloads.rs | 1 + src/test/ui/sepcomp/sepcomp-unwind.rs | 1 + src/test/ui/structs-enums/unit-like-struct-drop-run.rs | 1 + src/test/ui/test-attrs/test-should-fail-good-message.rs | 1 + src/test/ui/threads-sendsync/task-stderr.rs | 1 + src/test/ui/threads-sendsync/unwind-resource.rs | 1 + src/test/ui/unwind-unique.rs | 1 + 62 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs index c8559d2472824..2b3ece67b34a0 100644 --- a/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(overflowing_literals)] // Test that we cleanup a fixed size Box<[D; k]> properly when D has a diff --git a/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs index e75051caabcc3..c0ca458750776 100644 --- a/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs +++ b/src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(overflowing_literals)] // Test that we cleanup dynamic sized Box<[D]> properly when D has a diff --git a/src/test/ui/array-slice-vec/nested-vec-3.rs b/src/test/ui/array-slice-vec/nested-vec-3.rs index 96497a53d308e..b3ae683a8a61a 100644 --- a/src/test/ui/array-slice-vec/nested-vec-3.rs +++ b/src/test/ui/array-slice-vec/nested-vec-3.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(overflowing_literals)] // ignore-emscripten no threads support diff --git a/src/test/ui/array-slice-vec/slice-panic-1.rs b/src/test/ui/array-slice-vec/slice-panic-1.rs index 4134c62377835..3829078aba592 100644 --- a/src/test/ui/array-slice-vec/slice-panic-1.rs +++ b/src/test/ui/array-slice-vec/slice-panic-1.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support diff --git a/src/test/ui/array-slice-vec/slice-panic-2.rs b/src/test/ui/array-slice-vec/slice-panic-2.rs index 2f7178fb3e132..d83c611d3bb55 100644 --- a/src/test/ui/array-slice-vec/slice-panic-2.rs +++ b/src/test/ui/array-slice-vec/slice-panic-2.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs index f8caebcb8764e..5e71229beb5f9 100644 --- a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs +++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs @@ -2,6 +2,7 @@ // be talking about `async fn`s instead. Should also test what happens when it panics. // run-fail +// needs-unwind // error-pattern: thread 'main' panicked at '`async fn` resumed after panicking' // edition:2018 // ignore-wasm no panic or subprocess support diff --git a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs index ea4a9e5afa501..684172ca61cca 100644 --- a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs +++ b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // Check that partially moved from function parameters are dropped after the // named bindings that move from them. diff --git a/src/test/ui/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs index 2caedb649a35a..3623c4a4dd05d 100644 --- a/src/test/ui/builtin-clone-unwind.rs +++ b/src/test/ui/builtin-clone-unwind.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(unused_variables)] #![allow(unused_imports)] diff --git a/src/test/ui/catch-unwind-bang.rs b/src/test/ui/catch-unwind-bang.rs index f181991713b2c..b31b5cab5b724 100644 --- a/src/test/ui/catch-unwind-bang.rs +++ b/src/test/ui/catch-unwind-bang.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default fn worker() -> ! { diff --git a/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs b/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs index eadbe44a8e9de..6cd3781b76055 100644 --- a/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(unused_must_use)] #![allow(dead_code)] diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed index 7df0dd76b4456..89f3931418dac 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed @@ -1,4 +1,5 @@ // run-rustfix +// needs-unwind #![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs index d02fac7c66952..6b0b10521740e 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs @@ -1,4 +1,5 @@ // run-rustfix +// needs-unwind #![deny(rust_2021_incompatible_closure_captures)] //~^ NOTE: the lint level is defined here diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr index 74f85b6ebaac5..6594ec316532a 100644 --- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr +++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr @@ -1,5 +1,5 @@ error: changes to closure capture in Rust 2021 will affect which traits the closure implements - --> $DIR/mir_calls_to_shims.rs:20:38 + --> $DIR/mir_calls_to_shims.rs:21:38 | LL | let result = panic::catch_unwind(move || { | ^^^^^^^ @@ -11,7 +11,7 @@ LL | f.0() | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0` | note: the lint level is defined here - --> $DIR/mir_calls_to_shims.rs:3:9 + --> $DIR/mir_calls_to_shims.rs:4:9 | LL | #![deny(rust_2021_incompatible_closure_captures)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/drop/drop-trait-enum.rs b/src/test/ui/drop/drop-trait-enum.rs index 4ab8f733ad75a..d2b77650a9d5c 100644 --- a/src/test/ui/drop/drop-trait-enum.rs +++ b/src/test/ui/drop/drop-trait-enum.rs @@ -3,6 +3,7 @@ #![allow(unused_assignments)] #![allow(unused_variables)] // ignore-emscripten no threads support +// needs-unwind use std::thread; use std::sync::mpsc::{channel, Sender}; diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index c0bf0bdf731e6..13bd71ecb3389 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -4,6 +4,7 @@ // * Dropping one of the values panics while dropping the future. // run-pass +// needs-unwind // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 7bb43d5b50360..736123ed1198f 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/drop/terminate-in-initializer.rs b/src/test/ui/drop/terminate-in-initializer.rs index c9cb932e62af0..66f267aa7c7d8 100644 --- a/src/test/ui/drop/terminate-in-initializer.rs +++ b/src/test/ui/drop/terminate-in-initializer.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support // Issue #787 diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index 74c6e501c9136..7a91cbdc2f5d4 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten no threads support diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index bc15fcb0e3996..e84ff41b344a7 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten no threads support diff --git a/src/test/ui/generator/generator-resume-after-panic.rs b/src/test/ui/generator/generator-resume-after-panic.rs index 55704f40e9f2b..f2e67f1f750cc 100644 --- a/src/test/ui/generator/generator-resume-after-panic.rs +++ b/src/test/ui/generator/generator-resume-after-panic.rs @@ -1,4 +1,5 @@ // run-fail +// needs-unwind // error-pattern:generator resumed after panicking // ignore-emscripten no processes diff --git a/src/test/ui/generator/panic-drops-resume.rs b/src/test/ui/generator/panic-drops-resume.rs index 29f4788b2757f..8d8eb6a97b15a 100644 --- a/src/test/ui/generator/panic-drops-resume.rs +++ b/src/test/ui/generator/panic-drops-resume.rs @@ -1,6 +1,7 @@ //! Tests that panics inside a generator will correctly drop the initial resume argument. // run-pass +// needs-unwind // ignore-wasm no unwind support // ignore-emscripten no unwind support diff --git a/src/test/ui/generator/panic-drops.rs b/src/test/ui/generator/panic-drops.rs index c9a201725aea2..a9de4e7fc7d25 100644 --- a/src/test/ui/generator/panic-drops.rs +++ b/src/test/ui/generator/panic-drops.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/generator/panic-safe.rs b/src/test/ui/generator/panic-safe.rs index 500a3c9c2950e..14a0c8dbaf1da 100644 --- a/src/test/ui/generator/panic-safe.rs +++ b/src/test/ui/generator/panic-safe.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/generator/resume-after-return.rs b/src/test/ui/generator/resume-after-return.rs index efed08bd4708f..538609b981adf 100644 --- a/src/test/ui/generator/resume-after-return.rs +++ b/src/test/ui/generator/resume-after-return.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 324bba15e4350..a1cfee944c8bd 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // revisions: mir thir // [thir]compile-flags: -Zthir-unsafeck diff --git a/src/test/ui/issues/issue-14875.rs b/src/test/ui/issues/issue-14875.rs index 0d95d168b3db3..aaef2aab9fc76 100644 --- a/src/test/ui/issues/issue-14875.rs +++ b/src/test/ui/issues/issue-14875.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // Check that values are not leaked when a dtor panics (#14875) diff --git a/src/test/ui/issues/issue-25089.rs b/src/test/ui/issues/issue-25089.rs index cf261d43c55cb..0f0f78623a212 100644 --- a/src/test/ui/issues/issue-25089.rs +++ b/src/test/ui/issues/issue-25089.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support use std::thread; diff --git a/src/test/ui/issues/issue-26655.rs b/src/test/ui/issues/issue-26655.rs index 4c01183a44060..cb386c908a489 100644 --- a/src/test/ui/issues/issue-26655.rs +++ b/src/test/ui/issues/issue-26655.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support // Check that the destructors of simple enums are run on unwinding diff --git a/src/test/ui/issues/issue-29485.rs b/src/test/ui/issues/issue-29485.rs index 6b2fb7126e3df..8d58ee6d92c4b 100644 --- a/src/test/ui/issues/issue-29485.rs +++ b/src/test/ui/issues/issue-29485.rs @@ -1,6 +1,7 @@ // run-pass #![allow(unused_attributes)] // aux-build:issue-29485.rs +// needs-unwind // ignore-emscripten no threads #[feature(recover)] diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs index 8ede8143ea657..01c3ec64861fe 100644 --- a/src/test/ui/issues/issue-29948.rs +++ b/src/test/ui/issues/issue-29948.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-30018-panic.rs b/src/test/ui/issues/issue-30018-panic.rs index 50749b0c742f2..cba3055a22111 100644 --- a/src/test/ui/issues/issue-30018-panic.rs +++ b/src/test/ui/issues/issue-30018-panic.rs @@ -4,6 +4,7 @@ // spawned thread to isolate the expected error result from the // SIGTRAP injected by the drop-flag consistency checking. +// needs-unwind // ignore-emscripten no threads support struct Foo; diff --git a/src/test/ui/issues/issue-43853.rs b/src/test/ui/issues/issue-43853.rs index 47c3ab59aa2eb..3162c091c8786 100644 --- a/src/test/ui/issues/issue-43853.rs +++ b/src/test/ui/issues/issue-43853.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-46519.rs b/src/test/ui/issues/issue-46519.rs index cca0995d4ca10..9bd3c0948517b 100644 --- a/src/test/ui/issues/issue-46519.rs +++ b/src/test/ui/issues/issue-46519.rs @@ -1,6 +1,7 @@ // run-pass // compile-flags:--test -O +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default #[test] diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs index 5a0394ae760e9..15f25f1ca5373 100644 --- a/src/test/ui/iterators/iter-count-overflow-debug.rs +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -1,5 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs index 733ee0c46cc3d..65124c282412c 100644 --- a/src/test/ui/iterators/iter-position-overflow-debug.rs +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -1,5 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs index 67605d2fcc253..e16f984de79a6 100644 --- a/src/test/ui/iterators/iter-step-overflow-debug.rs +++ b/src/test/ui/iterators/iter-step-overflow-debug.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs index b7667d1bbf6d9..d8ce43848a77e 100644 --- a/src/test/ui/iterators/iter-sum-overflow-debug.rs +++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs index 04ca7f8a31534..bc8dcbdbb0e03 100644 --- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs +++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C overflow-checks diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index 780e158fe0b8f..dfd58b25d089d 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(unused_imports)] // Ideally, any macro call with a trailing comma should behave // identically to a call without the comma. diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs index 6f13d5612ce51..42eaab77da9f1 100644 --- a/src/test/ui/mir/mir_calls_to_shims.rs +++ b/src/test/ui/mir/mir_calls_to_shims.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs index 22c804abf5cc8..853efb0fed2b9 100644 --- a/src/test/ui/mir/mir_drop_order.rs +++ b/src/test/ui/mir/mir_drop_order.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default use std::cell::RefCell; diff --git a/src/test/ui/mir/mir_drop_panics.rs b/src/test/ui/mir/mir_drop_panics.rs index bf269ee901b93..b4093d704150a 100644 --- a/src/test/ui/mir/mir_drop_panics.rs +++ b/src/test/ui/mir/mir_drop_panics.rs @@ -1,4 +1,5 @@ // run-fail +// needs-unwind // error-pattern:panic 1 // error-pattern:drop 2 // ignore-emscripten no processes diff --git a/src/test/ui/mir/mir_dynamic_drops_3.rs b/src/test/ui/mir/mir_dynamic_drops_3.rs index eb76fdff88647..2bcd9fac55cd5 100644 --- a/src/test/ui/mir/mir_dynamic_drops_3.rs +++ b/src/test/ui/mir/mir_dynamic_drops_3.rs @@ -1,4 +1,5 @@ // run-fail +// needs-unwind // error-pattern:unwind happens // error-pattern:drop 3 // error-pattern:drop 2 diff --git a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs index 9c6dff7e1a6ca..d63ba8cb03e9a 100644 --- a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs +++ b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs @@ -1,6 +1,7 @@ // run-pass // compile-flags: -C overflow-checks=on // ignore-emscripten no threads support +// needs-unwind use std::thread; diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs index 101c5d50b20b9..f857d4f4c7f27 100644 --- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs +++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -1,5 +1,6 @@ // run-pass // compile-flags: -C debug_assertions=yes +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten dies with an LLVM error diff --git a/src/test/ui/panics/panic-handler-chain.rs b/src/test/ui/panics/panic-handler-chain.rs index 93044b5cb2591..73d6e790dff57 100644 --- a/src/test/ui/panics/panic-handler-chain.rs +++ b/src/test/ui/panics/panic-handler-chain.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(stable_features)] // ignore-emscripten no threads support diff --git a/src/test/ui/panics/panic-handler-flail-wildly.rs b/src/test/ui/panics/panic-handler-flail-wildly.rs index 6badd203842ff..679dc7de87aba 100644 --- a/src/test/ui/panics/panic-handler-flail-wildly.rs +++ b/src/test/ui/panics/panic-handler-flail-wildly.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(stable_features)] #![allow(unused_must_use)] diff --git a/src/test/ui/panics/panic-handler-set-twice.rs b/src/test/ui/panics/panic-handler-set-twice.rs index 0312ed221ca35..2744530209026 100644 --- a/src/test/ui/panics/panic-handler-set-twice.rs +++ b/src/test/ui/panics/panic-handler-set-twice.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(unused_variables)] #![allow(stable_features)] diff --git a/src/test/ui/panics/panic-in-dtor-drops-fields.rs b/src/test/ui/panics/panic-in-dtor-drops-fields.rs index caddd942dc0a0..c0963aa3114dc 100644 --- a/src/test/ui/panics/panic-in-dtor-drops-fields.rs +++ b/src/test/ui/panics/panic-in-dtor-drops-fields.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(dead_code)] #![allow(non_upper_case_globals)] diff --git a/src/test/ui/panics/panic-recover-propagate.rs b/src/test/ui/panics/panic-recover-propagate.rs index 7969336ca749b..e110d94b65614 100644 --- a/src/test/ui/panics/panic-recover-propagate.rs +++ b/src/test/ui/panics/panic-recover-propagate.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/src/test/ui/privacy/reachable-unnameable-items.rs b/src/test/ui/privacy/reachable-unnameable-items.rs index f1e53a0d8b426..1c91541e64229 100644 --- a/src/test/ui/privacy/reachable-unnameable-items.rs +++ b/src/test/ui/privacy/reachable-unnameable-items.rs @@ -1,5 +1,6 @@ // run-pass // ignore-wasm32-bare compiled with panic=abort by default +// needs-unwind // aux-build:reachable-unnameable-items.rs extern crate reachable_unnameable_items; diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs index 418178d0f0ead..21a4547d11e1c 100644 --- a/src/test/ui/proc-macro/expand-with-a-macro.rs +++ b/src/test/ui/proc-macro/expand-with-a-macro.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // aux-build:expand-with-a-macro.rs // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs index 0bd7bf3d51a78..cd57d9bca9429 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -1,5 +1,6 @@ // compile-flags: --test // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs index f0850d5c1f1e9..b067994a5c6d8 100644 --- a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs +++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // revisions: default mir-opt //[mir-opt] compile-flags: -Zmir-opt-level=4 diff --git a/src/test/ui/rfcs/rfc1857-drop-order.rs b/src/test/ui/rfcs/rfc1857-drop-order.rs index 7923aa7c0e22f..243b7fb6fadec 100644 --- a/src/test/ui/rfcs/rfc1857-drop-order.rs +++ b/src/test/ui/rfcs/rfc1857-drop-order.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default #![allow(dead_code, unreachable_code)] diff --git a/src/test/ui/runtime/rt-explody-panic-payloads.rs b/src/test/ui/runtime/rt-explody-panic-payloads.rs index dc193582c6a50..eb5bf8f67a849 100644 --- a/src/test/ui/runtime/rt-explody-panic-payloads.rs +++ b/src/test/ui/runtime/rt-explody-panic-payloads.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no processes // ignore-sgx no processes // ignore-wasm32-bare no unwinding panic diff --git a/src/test/ui/sepcomp/sepcomp-unwind.rs b/src/test/ui/sepcomp/sepcomp-unwind.rs index 50a4e043943f0..a59e25a273e70 100644 --- a/src/test/ui/sepcomp/sepcomp-unwind.rs +++ b/src/test/ui/sepcomp/sepcomp-unwind.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(dead_code)] // compile-flags: -C codegen-units=3 // ignore-emscripten no threads support diff --git a/src/test/ui/structs-enums/unit-like-struct-drop-run.rs b/src/test/ui/structs-enums/unit-like-struct-drop-run.rs index 980fd97e2c678..1e9c269a4d375 100644 --- a/src/test/ui/structs-enums/unit-like-struct-drop-run.rs +++ b/src/test/ui/structs-enums/unit-like-struct-drop-run.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support // Make sure the destructor is run for unit-like structs. diff --git a/src/test/ui/test-attrs/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs index 9fa759f9eb483..3260b6938f07d 100644 --- a/src/test/ui/test-attrs/test-should-fail-good-message.rs +++ b/src/test/ui/test-attrs/test-should-fail-good-message.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #[test] diff --git a/src/test/ui/threads-sendsync/task-stderr.rs b/src/test/ui/threads-sendsync/task-stderr.rs index 78145e337dafb..68d226ffbaee3 100644 --- a/src/test/ui/threads-sendsync/task-stderr.rs +++ b/src/test/ui/threads-sendsync/task-stderr.rs @@ -1,5 +1,6 @@ // run-pass // ignore-emscripten no threads support +// needs-unwind #![feature(internal_output_capture)] diff --git a/src/test/ui/threads-sendsync/unwind-resource.rs b/src/test/ui/threads-sendsync/unwind-resource.rs index a063bef0822f2..6950a9c40d27d 100644 --- a/src/test/ui/threads-sendsync/unwind-resource.rs +++ b/src/test/ui/threads-sendsync/unwind-resource.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind #![allow(non_camel_case_types)] // ignore-emscripten no threads support diff --git a/src/test/ui/unwind-unique.rs b/src/test/ui/unwind-unique.rs index 7ca53b664ac6c..50ecf751a86db 100644 --- a/src/test/ui/unwind-unique.rs +++ b/src/test/ui/unwind-unique.rs @@ -1,4 +1,5 @@ // run-pass +// needs-unwind // ignore-emscripten no threads support use std::thread; From 203cf2d3668e38dfa3088763789d2541c5943ae7 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Sat, 4 Dec 2021 10:32:09 +0100 Subject: [PATCH 7/7] Add rsplit_array variants to slices and arrays --- library/core/src/array/mod.rs | 78 +++++++++++++++++++++++++++++++++++ library/core/src/slice/mod.rs | 78 +++++++++++++++++++++++++++++++++++ library/core/tests/array.rs | 33 +++++++++++++++ library/core/tests/slice.rs | 33 +++++++++++++++ 4 files changed, 222 insertions(+) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 23fd1453e54d1..5e295ffbff740 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -645,6 +645,84 @@ impl [T; N] { pub fn split_array_mut(&mut self) -> (&mut [T; M], &mut [T]) { (&mut self[..]).split_array_mut::() } + + /// Divides one array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = [1, 2, 3, 4, 5, 6]; + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<0>(); + /// assert_eq!(left, &[1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<2>(); + /// assert_eq!(left, &[1, 2, 3, 4]); + /// assert_eq!(right, &[5, 6]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<6>(); + /// assert_eq!(left, &[]); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_ref(&self) -> (&[T], &[T; M]) { + (&self[..]).rsplit_array_ref::() + } + + /// Divides one mutable array reference into two at an index from the end. + /// + /// The first will contain all indices from `[0, N - M)` (excluding + /// the index `N - M` itself) and the second will contain all + /// indices from `[N - M, N)` (excluding the index `N` itself). + /// + /// # Panics + /// + /// Panics if `M > N`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = [1, 0, 3, 0, 5, 6]; + /// let (left, right) = v.rsplit_array_mut::<4>(); + /// assert_eq!(left, &mut [1, 0]); + /// assert_eq!(right, &mut [3, 0, 5, 6][..]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable( + feature = "split_array", + reason = "return type should have array as 2nd element", + issue = "90091" + )] + #[inline] + pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; M]) { + (&mut self[..]).rsplit_array_mut::() + } } /// Pulls `N` items from `iter` and returns them as an array. If the iterator diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index a3f59d3075954..f9ea99ea8aa5c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1705,6 +1705,84 @@ impl [T] { unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) } } + /// Divides one slice into an array and a remainder slice at an index from + /// the end. + /// + /// The slice will contain all indices from `[0, len - N)` (excluding + /// the index `len - N` itself) and the array will contain all + /// indices from `[len - N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let v = &[1, 2, 3, 4, 5, 6][..]; + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<0>(); + /// assert_eq!(left, [1, 2, 3, 4, 5, 6]); + /// assert_eq!(right, &[]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<2>(); + /// assert_eq!(left, [1, 2, 3, 4]); + /// assert_eq!(right, &[5, 6]); + /// } + /// + /// { + /// let (left, right) = v.rsplit_array_ref::<6>(); + /// assert_eq!(left, []); + /// assert_eq!(right, &[1, 2, 3, 4, 5, 6]); + /// } + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn rsplit_array_ref(&self) -> (&[T], &[T; N]) { + assert!(N <= self.len()); + let (a, b) = self.split_at(self.len() - N); + // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at) + unsafe { (a, &*(b.as_ptr() as *const [T; N])) } + } + + /// Divides one mutable slice into an array and a remainder slice at an + /// index from the end. + /// + /// The slice will contain all indices from `[0, len - N)` (excluding + /// the index `N` itself) and the array will contain all + /// indices from `[len - N, len)` (excluding the index `len` itself). + /// + /// # Panics + /// + /// Panics if `N > len`. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_array)] + /// + /// let mut v = &mut [1, 0, 3, 0, 5, 6][..]; + /// let (left, right) = v.rsplit_array_mut::<4>(); + /// assert_eq!(left, [1, 0]); + /// assert_eq!(right, &mut [3, 0, 5, 6]); + /// left[1] = 2; + /// right[1] = 4; + /// assert_eq!(v, [1, 2, 3, 4, 5, 6]); + /// ``` + #[unstable(feature = "split_array", reason = "new API", issue = "90091")] + #[inline] + pub fn rsplit_array_mut(&mut self) -> (&mut [T], &mut [T; N]) { + assert!(N <= self.len()); + let (a, b) = self.split_at_mut(self.len() - N); + // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut) + unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) } + } + /// Returns an iterator over subslices separated by elements that match /// `pred`. The matched element is not contained in the subslices. /// diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index d212a3a3a05da..8524a0bf8dd6a 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -459,6 +459,23 @@ fn array_split_array_mut() { } } +#[test] +fn array_rsplit_array_mut() { + let mut v = [1, 2, 3, 4, 5, 6]; + + { + let (left, right) = v.rsplit_array_mut::<0>(); + assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]); + assert_eq!(right, &mut []); + } + + { + let (left, right) = v.rsplit_array_mut::<6>(); + assert_eq!(left, &mut []); + assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); + } +} + #[should_panic] #[test] fn array_split_array_ref_out_of_bounds() { @@ -475,6 +492,22 @@ fn array_split_array_mut_out_of_bounds() { v.split_array_mut::<7>(); } +#[should_panic] +#[test] +fn array_rsplit_array_ref_out_of_bounds() { + let v = [1, 2, 3, 4, 5, 6]; + + v.rsplit_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn array_rsplit_array_mut_out_of_bounds() { + let mut v = [1, 2, 3, 4, 5, 6]; + + v.rsplit_array_mut::<7>(); +} + #[test] fn array_intoiter_advance_by() { use std::cell::Cell; diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 281df8a1326d0..20e2d8d47c0f5 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2219,6 +2219,23 @@ fn slice_split_array_mut() { } } +#[test] +fn slice_rsplit_array_mut() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + { + let (left, right) = v.rsplit_array_mut::<0>(); + assert_eq!(left, [1, 2, 3, 4, 5, 6]); + assert_eq!(right, &mut []); + } + + { + let (left, right) = v.rsplit_array_mut::<6>(); + assert_eq!(left, []); + assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]); + } +} + #[should_panic] #[test] fn slice_split_array_ref_out_of_bounds() { @@ -2235,6 +2252,22 @@ fn slice_split_array_mut_out_of_bounds() { v.split_array_mut::<7>(); } +#[should_panic] +#[test] +fn slice_rsplit_array_ref_out_of_bounds() { + let v = &[1, 2, 3, 4, 5, 6][..]; + + v.rsplit_array_ref::<7>(); +} + +#[should_panic] +#[test] +fn slice_rsplit_array_mut_out_of_bounds() { + let v = &mut [1, 2, 3, 4, 5, 6][..]; + + v.rsplit_array_mut::<7>(); +} + macro_rules! take_tests { (slice: &[], $($tts:tt)*) => { take_tests!(ty: &[()], slice: &[], $($tts)*);