From f398a49829e837ffc62f2242e549248b7541e430 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 21 Mar 2021 20:20:58 +0100 Subject: [PATCH 01/20] Add test for io::Error's size. --- library/std/src/io/error/tests.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index 0cce9368c8089..eb051c33f0929 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -1,9 +1,15 @@ use super::{Custom, Error, ErrorKind, Repr}; use crate::error; use crate::fmt; +use crate::mem::size_of; use crate::sys::decode_error_kind; use crate::sys::os::error_string; +#[test] +fn test_size() { + assert!(size_of::() <= size_of::<[usize; 2]>()); +} + #[test] fn test_debug_error() { let code = 6; From 2da9856f171f909dd072bd59d190a036dc13fc38 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 21 Mar 2021 20:21:51 +0100 Subject: [PATCH 02/20] Add internal io::Error::new_const tot avoid allocations. --- library/std/src/io/error.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index ba0f0a0cd714a..f4802c32a723f 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -69,6 +69,8 @@ impl fmt::Debug for Error { enum Repr { Os(i32), Simple(ErrorKind), + // &str is a fat pointer, but &&str is a thin pointer. + SimpleMessage(ErrorKind, &'static &'static str), Custom(Box), } @@ -259,6 +261,18 @@ impl Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })) } } + /// Creates a new I/O error from a known kind of error as well as a + /// constant message. + /// + /// This function not allocate. + /// + /// This function should maybe change to + /// `new_const(kind: ErrorKind)` + /// in the future, when const generics allows that. + pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error { + Self { repr: Repr::SimpleMessage(kind, message) } + } + /// Returns an error representing the last OS error which occurred. /// /// This function reads the value of `errno` for the target platform (e.g. @@ -342,6 +356,7 @@ impl Error { Repr::Os(i) => Some(i), Repr::Custom(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, } } @@ -377,6 +392,7 @@ impl Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => Some(&*c.error), } } @@ -448,6 +464,7 @@ impl Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref mut c) => Some(&mut *c.error), } } @@ -484,6 +501,7 @@ impl Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(c) => Some(c.error), } } @@ -512,6 +530,7 @@ impl Error { Repr::Os(code) => sys::decode_error_kind(code), Repr::Custom(ref c) => c.kind, Repr::Simple(kind) => kind, + Repr::SimpleMessage(kind, _) => kind, } } } @@ -527,6 +546,9 @@ impl fmt::Debug for Repr { .finish(), Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt), Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(), + Repr::SimpleMessage(kind, &message) => { + fmt.debug_struct("Error").field("kind", &kind).field("message", &message).finish() + } } } } @@ -541,6 +563,7 @@ impl fmt::Display for Error { } Repr::Custom(ref c) => c.error.fmt(fmt), Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), + Repr::SimpleMessage(_, &msg) => msg.fmt(fmt), } } } @@ -551,6 +574,7 @@ impl error::Error for Error { fn description(&self) -> &str { match self.repr { Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(), + Repr::SimpleMessage(_, &msg) => msg, Repr::Custom(ref c) => c.error.description(), } } @@ -560,6 +584,7 @@ impl error::Error for Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => c.error.cause(), } } @@ -568,6 +593,7 @@ impl error::Error for Error { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, + Repr::SimpleMessage(..) => None, Repr::Custom(ref c) => c.error.source(), } } From 96783625a0a2906d70690a5d76f83b1ccc028434 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 21 Mar 2021 20:22:26 +0100 Subject: [PATCH 03/20] Add test for io::Error::new_const. --- library/std/src/io/error/tests.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs index eb051c33f0929..5098a46313de3 100644 --- a/library/std/src/io/error/tests.rs +++ b/library/std/src/io/error/tests.rs @@ -57,3 +57,13 @@ fn test_downcasting() { let extracted = err.into_inner().unwrap(); extracted.downcast::().unwrap(); } + +#[test] +fn test_const() { + const E: Error = Error::new_const(ErrorKind::NotFound, &"hello"); + + assert_eq!(E.kind(), ErrorKind::NotFound); + assert_eq!(E.to_string(), "hello"); + assert!(format!("{:?}", E).contains("\"hello\"")); + assert!(format!("{:?}", E).contains("NotFound")); +} From 7b71719faf5ba6a230d097fddb288f79ccc570f1 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 21 Mar 2021 20:22:38 +0100 Subject: [PATCH 04/20] Use io::Error::new_const everywhere to avoid allocations. --- library/std/src/ffi/c_str.rs | 2 +- library/std/src/fs.rs | 5 +- library/std/src/io/buffered/bufwriter.rs | 4 +- library/std/src/io/cursor.rs | 8 +- library/std/src/io/impls.rs | 4 +- library/std/src/io/mod.rs | 16 +- library/std/src/io/tests.rs | 4 +- library/std/src/net/mod.rs | 2 +- library/std/src/net/udp.rs | 2 +- library/std/src/sys/hermit/fd.rs | 6 +- library/std/src/sys/hermit/fs.rs | 12 +- library/std/src/sys/hermit/mod.rs | 5 +- library/std/src/sys/hermit/net.rs | 140 +++++++++--------- library/std/src/sys/hermit/stdio.rs | 8 +- library/std/src/sys/hermit/thread.rs | 2 +- library/std/src/sys/sgx/mod.rs | 6 +- library/std/src/sys/sgx/net.rs | 12 +- library/std/src/sys/unix/android.rs | 6 +- library/std/src/sys/unix/ext/fs.rs | 6 +- library/std/src/sys/unix/ext/net/addr.rs | 12 +- library/std/src/sys/unix/fs.rs | 12 +- library/std/src/sys/unix/l4re.rs | 2 +- library/std/src/sys/unix/net.rs | 15 +- library/std/src/sys/unix/os.rs | 18 +-- .../src/sys/unix/process/process_fuchsia.rs | 17 ++- .../std/src/sys/unix/process/process_unix.rs | 14 +- library/std/src/sys/unsupported/common.rs | 2 +- library/std/src/sys/unsupported/os.rs | 4 +- .../sys/vxworks/process/process_vxworks.rs | 9 +- library/std/src/sys/wasi/ext/fs.rs | 8 +- library/std/src/sys/wasi/fs.rs | 2 +- library/std/src/sys/windows/fs.rs | 6 +- library/std/src/sys/windows/mod.rs | 4 +- library/std/src/sys/windows/net.rs | 12 +- library/std/src/sys/windows/process.rs | 2 +- library/std/src/sys/windows/stdio.rs | 12 +- library/std/src/sys_common/fs.rs | 4 +- library/std/src/sys_common/net.rs | 4 +- .../std/src/thread/available_concurrency.rs | 10 +- 39 files changed, 230 insertions(+), 189 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 945bfda1b7874..687ed61b95961 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -1036,7 +1036,7 @@ impl fmt::Display for NulError { impl From for io::Error { /// Converts a [`NulError`] into a [`io::Error`]. fn from(_: NulError) -> io::Error { - io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte") + io::Error::new_const(io::ErrorKind::InvalidInput, &"data provided contains a nul byte") } } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 43119c36cfec7..ccbc69a975c32 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2188,7 +2188,10 @@ impl DirBuilder { match path.parent() { Some(p) => self.create_dir_all(p)?, None => { - return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree")); + return Err(io::Error::new_const( + io::ErrorKind::Other, + &"failed to create whole tree", + )); } } match self.inner.mkdir(path) { diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 65bc2fcf00ae0..80f98bbbad366 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -164,9 +164,9 @@ impl BufWriter { match r { Ok(0) => { - return Err(Error::new( + return Err(Error::new_const( ErrorKind::WriteZero, - "failed to write the buffered data", + &"failed to write the buffered data", )); } Ok(n) => guard.consume(n), diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index bbee2cc98425e..9021b47006538 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -229,9 +229,9 @@ where self.pos = n; Ok(self.pos) } - None => Err(Error::new( + None => Err(Error::new_const( ErrorKind::InvalidInput, - "invalid seek to a negative or overflowing position", + &"invalid seek to a negative or overflowing position", )), } } @@ -328,9 +328,9 @@ fn slice_write_vectored( // Resizing write implementation fn vec_write(pos_mut: &mut u64, vec: &mut Vec, buf: &[u8]) -> io::Result { let pos: usize = (*pos_mut).try_into().map_err(|_| { - Error::new( + Error::new_const( ErrorKind::InvalidInput, - "cursor position exceeds maximum possible vector length", + &"cursor position exceeds maximum possible vector length", ) })?; // Make sure the internal buffer is as least as big as where we diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 9870cfc4c95c3..6891bd8a66437 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -263,7 +263,7 @@ impl Read for &[u8] { #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { if buf.len() > self.len() { - return Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")); + return Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")); } let (a, b) = self.split_at(buf.len()); @@ -345,7 +345,7 @@ impl Write for &mut [u8] { if self.write(data)? == data.len() { Ok(()) } else { - Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")) + Err(Error::new_const(ErrorKind::WriteZero, &"failed to write whole buffer")) } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 17002e3b8602d..7dec55fb1ab1f 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -333,7 +333,7 @@ where let ret = f(g.buf); if str::from_utf8(&g.buf[g.len..]).is_err() { ret.and_then(|_| { - Err(Error::new(ErrorKind::InvalidData, "stream did not contain valid UTF-8")) + Err(Error::new_const(ErrorKind::InvalidData, &"stream did not contain valid UTF-8")) }) } else { g.len = g.buf.len(); @@ -429,7 +429,7 @@ pub(crate) fn default_read_exact(this: &mut R, mut buf: &mut [ } } if !buf.is_empty() { - Err(Error::new(ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(Error::new_const(ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -1432,7 +1432,10 @@ pub trait Write { while !buf.is_empty() { match self.write(buf) { Ok(0) => { - return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")); + return Err(Error::new_const( + ErrorKind::WriteZero, + &"failed to write whole buffer", + )); } Ok(n) => buf = &buf[n..], Err(ref e) if e.kind() == ErrorKind::Interrupted => {} @@ -1497,7 +1500,10 @@ pub trait Write { while !bufs.is_empty() { match self.write_vectored(bufs) { Ok(0) => { - return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer")); + return Err(Error::new_const( + ErrorKind::WriteZero, + &"failed to write whole buffer", + )); } Ok(n) => bufs = IoSlice::advance(bufs, n), Err(ref e) if e.kind() == ErrorKind::Interrupted => {} @@ -1571,7 +1577,7 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(Error::new(ErrorKind::Other, "formatter error")) + Err(Error::new_const(ErrorKind::Other, &"formatter error")) } } } diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index a85dd0d982715..2b14e16150317 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -152,12 +152,12 @@ fn take_eof() { impl Read for R { fn read(&mut self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(io::ErrorKind::Other, "")) + Err(io::Error::new_const(io::ErrorKind::Other, &"")) } } impl BufRead for R { fn fill_buf(&mut self) -> io::Result<&[u8]> { - Err(io::Error::new(io::ErrorKind::Other, "")) + Err(io::Error::new_const(io::ErrorKind::Other, &"")) } fn consume(&mut self, _amt: usize) {} } diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs index d4b1552fec5ff..d814e9b25ba9a 100644 --- a/library/std/src/net/mod.rs +++ b/library/std/src/net/mod.rs @@ -88,6 +88,6 @@ where } } Err(last_err.unwrap_or_else(|| { - Error::new(ErrorKind::InvalidInput, "could not resolve to any addresses") + Error::new_const(ErrorKind::InvalidInput, &"could not resolve to any addresses") })) } diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs index 2377a76a33de9..b9af5992dffdf 100644 --- a/library/std/src/net/udp.rs +++ b/library/std/src/net/udp.rs @@ -173,7 +173,7 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], addr: A) -> io::Result { match addr.to_socket_addrs()?.next() { Some(addr) => self.0.send_to(buf, &addr), - None => Err(Error::new(ErrorKind::InvalidInput, "no addresses to send data to")), + None => Err(Error::new_const(ErrorKind::InvalidInput, &"no addresses to send data to")), } } diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index 97d1a38b41ab1..1c0515a150398 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -46,7 +46,7 @@ impl FileDesc { self.duplicate_path(&[]) } pub fn duplicate_path(&self, _path: &[u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "duplicate isn't supported")) + Err(io::Error::new_const(ErrorKind::Other, &"duplicate isn't supported")) } pub fn nonblocking(&self) -> io::Result { @@ -54,11 +54,11 @@ impl FileDesc { } pub fn set_cloexec(&self) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "cloexec isn't supported")) + Err(io::Error::new_const(ErrorKind::Other, &"cloexec isn't supported")) } pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "nonblocking isn't supported")) + Err(io::Error::new_const(ErrorKind::Other, &"nonblocking isn't supported")) } } diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs index 1807655e97170..0f33282fa8370 100644 --- a/library/std/src/sys/hermit/fs.rs +++ b/library/std/src/sys/hermit/fs.rs @@ -226,7 +226,7 @@ impl OpenOptions { (false, _, true) => Ok(O_WRONLY | O_APPEND), (true, _, true) => Ok(O_RDWR | O_APPEND), (false, false, false) => { - Err(io::Error::new(ErrorKind::InvalidInput, "invalid access mode")) + Err(io::Error::new_const(ErrorKind::InvalidInput, &"invalid access mode")) } } } @@ -236,12 +236,18 @@ impl OpenOptions { (true, false) => {} (false, false) => { if self.truncate || self.create || self.create_new { - return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"invalid creation mode", + )); } } (_, true) => { if self.truncate && !self.create_new { - return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"invalid creation mode", + )); } } } diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index f185635b7a0a6..65403c090547a 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -54,7 +54,10 @@ pub fn unsupported() -> crate::io::Result { } pub fn unsupported_err() -> crate::io::Error { - crate::io::Error::new(crate::io::ErrorKind::Other, "operation not supported on HermitCore yet") + crate::io::Error::new_const( + crate::io::ErrorKind::Other, + &"operation not supported on HermitCore yet", + ) } // This enum is used as the storage for a bunch of types which can't actually diff --git a/library/std/src/sys/hermit/net.rs b/library/std/src/sys/hermit/net.rs index 8a788a9265f63..7053487ccfbe0 100644 --- a/library/std/src/sys/hermit/net.rs +++ b/library/std/src/sys/hermit/net.rs @@ -14,7 +14,10 @@ use crate::time::Duration; /// if not, starts it. pub fn init() -> io::Result<()> { if abi::network_init() < 0 { - return Err(io::Error::new(ErrorKind::Other, "Unable to initialize network interface")); + return Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initialize network interface", + )); } Ok(()) @@ -47,9 +50,10 @@ impl TcpStream { match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), - _ => { - Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) - } + _ => Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initiate a connection on a socket", + )), } } @@ -60,15 +64,16 @@ impl TcpStream { Some(duration.as_millis() as u64), ) { Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))), - _ => { - Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket")) - } + _ => Err(io::Error::new_const( + ErrorKind::Other, + &"Unable to initiate a connection on a socket", + )), } } pub fn set_read_timeout(&self, duration: Option) -> io::Result<()> { abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64)) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) } pub fn set_write_timeout(&self, duration: Option) -> io::Result<()> { @@ -76,26 +81,28 @@ impl TcpStream { *self.0.as_inner(), duration.map(|d| d.as_millis() as u64), ) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to set timeout value")) } pub fn read_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner()).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + })?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn write_timeout(&self) -> io::Result> { - let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?; + let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner()).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to determine timeout value") + })?; Ok(duration.map(|d| Duration::from_millis(d))) } pub fn peek(&self, buf: &mut [u8]) -> io::Result { abi::tcpstream::peek(*self.0.as_inner(), buf) - .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) } pub fn read(&self, buffer: &mut [u8]) -> io::Result { @@ -107,7 +114,7 @@ impl TcpStream { for i in ioslice.iter_mut() { let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..]) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"Unable to read on socket"))?; if ret != 0 { size += ret; @@ -130,8 +137,9 @@ impl TcpStream { let mut size: usize = 0; for i in ioslice.iter() { - size += abi::tcpstream::write(*self.0.as_inner(), i) - .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?; + size += abi::tcpstream::write(*self.0.as_inner(), i).map_err(|_| { + io::Error::new_const(ErrorKind::Other, &"Unable to write on socket") + })?; } Ok(size) @@ -144,13 +152,13 @@ impl TcpStream { pub fn peer_addr(&self) -> io::Result { let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"peer_addr failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new(ErrorKind::Other, "peer_addr failed")); + return Err(io::Error::new_const(ErrorKind::Other, &"peer_addr failed")); } }; @@ -158,12 +166,12 @@ impl TcpStream { } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "socket_addr isn't supported")) + Err(io::Error::new_const(ErrorKind::Other, &"socket_addr isn't supported")) } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { abi::tcpstream::shutdown(*self.0.as_inner(), how as i32) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to shutdown socket")) } pub fn duplicate(&self) -> io::Result { @@ -172,31 +180,31 @@ impl TcpStream { pub fn set_nodelay(&self, mode: bool) -> io::Result<()> { abi::tcpstream::set_nodelay(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"set_nodelay failed")) } pub fn nodelay(&self) -> io::Result { abi::tcpstream::nodelay(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"nodelay failed")) } pub fn set_ttl(&self, tll: u32) -> io::Result<()> { abi::tcpstream::set_tll(*self.0.as_inner(), tll) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set TTL")) } pub fn ttl(&self) -> io::Result { abi::tcpstream::get_tll(*self.0.as_inner()) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to get TTL")) } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "take_error isn't supported")) + Err(io::Error::new_const(ErrorKind::Other, &"take_error isn't supported")) } pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> { abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode) - .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode")) + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"unable to set blocking mode")) } } @@ -222,12 +230,12 @@ impl TcpListener { pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port()) - .map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?; + .map_err(|_| io::Error::new_const(ErrorKind::Other, &"accept failed"))?; let saddr = match ipaddr { Ipv4(ref addr) => SocketAddr::new(IpAddr::V4(Ipv4Addr::from(addr.0)), port), Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port), _ => { - return Err(io::Error::new(ErrorKind::Other, "accept failed")); + return Err(io::Error::new_const(ErrorKind::Other, &"accept failed")); } }; @@ -239,27 +247,27 @@ impl TcpListener { } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn ttl(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn only_v6(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } } @@ -273,127 +281,127 @@ pub struct UdpSocket(abi::Handle); impl UdpSocket { pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn peer_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn socket_addr(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn duplicate(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn read_timeout(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn write_timeout(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn broadcast(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn multicast_loop_v4(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn multicast_ttl_v4(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn multicast_loop_v6(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_ttl(&self, _: u32) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn ttl(&self) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn take_error(&self) -> io::Result> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn recv(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn peek(&self, _: &mut [u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn send(&self, _: &[u8]) -> io::Result { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - Err(io::Error::new(ErrorKind::Other, "not supported")) + Err(io::Error::new_const(ErrorKind::Other, &"not supported")) } } diff --git a/library/std/src/sys/hermit/stdio.rs b/library/std/src/sys/hermit/stdio.rs index 82304dd6dc293..6bff13ca92cca 100644 --- a/library/std/src/sys/hermit/stdio.rs +++ b/library/std/src/sys/hermit/stdio.rs @@ -40,7 +40,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -52,7 +52,7 @@ impl io::Write for Stdout { unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Stdout is not able to print")) } else { Ok(len as usize) } @@ -81,7 +81,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) } else { Ok(len as usize) } @@ -93,7 +93,7 @@ impl io::Write for Stderr { unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { - Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Stderr is not able to print")) } else { Ok(len as usize) } diff --git a/library/std/src/sys/hermit/thread.rs b/library/std/src/sys/hermit/thread.rs index 7bd71e120de40..f35a3a8a80fc5 100644 --- a/library/std/src/sys/hermit/thread.rs +++ b/library/std/src/sys/hermit/thread.rs @@ -37,7 +37,7 @@ impl Thread { // The thread failed to start and as a result p was not consumed. Therefore, it is // safe to reconstruct the box so that it gets deallocated. drop(Box::from_raw(p)); - Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Unable to create thread!")) } else { Ok(Thread { tid: tid }) }; diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index b10bed621dbad..3cd245f40d967 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -50,7 +50,7 @@ pub fn unsupported() -> crate::io::Result { } pub fn unsupported_err() -> crate::io::Error { - crate::io::Error::new(ErrorKind::Other, "operation not supported on SGX yet") + crate::io::Error::new_const(ErrorKind::Other, &"operation not supported on SGX yet") } /// This function is used to implement various functions that doesn't exist, @@ -61,9 +61,9 @@ pub fn unsupported_err() -> crate::io::Error { pub fn sgx_ineffective(v: T) -> crate::io::Result { static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false); if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) { - Err(crate::io::Error::new( + Err(crate::io::Error::new_const( ErrorKind::Other, - "operation can't be trusted to have any effect on SGX", + &"operation can't be trusted to have any effect on SGX", )) } else { Ok(v) diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs index 3dd8267921e5e..c0c5d55548c5f 100644 --- a/library/std/src/sys/sgx/net.rs +++ b/library/std/src/sys/sgx/net.rs @@ -97,9 +97,9 @@ impl TcpStream { pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result { if dur == Duration::default() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } Self::connect(Ok(addr)) // FIXME: ignoring timeout @@ -108,9 +108,9 @@ impl TcpStream { pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { match dur { Some(dur) if dur == Duration::default() => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } _ => sgx_ineffective(()), @@ -120,9 +120,9 @@ impl TcpStream { pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { match dur { Some(dur) if dur == Duration::default() => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } _ => sgx_ineffective(()), diff --git a/library/std/src/sys/unix/android.rs b/library/std/src/sys/unix/android.rs index ea05ee3d7cedf..cf6aa31b7cfe3 100644 --- a/library/std/src/sys/unix/android.rs +++ b/library/std/src/sys/unix/android.rs @@ -96,7 +96,7 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { Some(f) => cvt_r(|| f(fd, size as i64)).map(drop), None => { if size > i32::MAX as u64 { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot truncate >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot truncate >2GB")) } else { cvt_r(|| ftruncate(fd, size as i32)).map(drop) } @@ -123,7 +123,7 @@ pub unsafe fn cvt_pread64( if let Ok(o) = offset.try_into() { cvt(pread(fd, buf, count, o)) } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pread >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pread >2GB")) } }) } @@ -141,7 +141,7 @@ pub unsafe fn cvt_pwrite64( if let Ok(o) = offset.try_into() { cvt(pwrite(fd, buf, count, o)) } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot pwrite >2GB")) + Err(io::Error::new_const(io::ErrorKind::InvalidInput, &"cannot pwrite >2GB")) } }) } diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs index ba75b9bac8035..76338c1bb0f6e 100644 --- a/library/std/src/sys/unix/ext/fs.rs +++ b/library/std/src/sys/unix/ext/fs.rs @@ -109,7 +109,7 @@ pub trait FileExt { } } if !buf.is_empty() { - Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -191,9 +191,9 @@ pub trait FileExt { while !buf.is_empty() { match self.write_at(buf, offset) { Ok(0) => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::WriteZero, - "failed to write whole buffer", + &"failed to write whole buffer", )); } Ok(n) => { diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs index 1f9036242eb59..6e7d1f1678a9e 100644 --- a/library/std/src/sys/unix/ext/net/addr.rs +++ b/library/std/src/sys/unix/ext/net/addr.rs @@ -29,16 +29,16 @@ pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, let bytes = path.as_os_str().as_bytes(); if bytes.contains(&0) { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "paths may not contain interior null bytes", + &"paths may not contain interior null bytes", )); } if bytes.len() >= addr.sun_path.len() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "path must be shorter than SUN_LEN", + &"path must be shorter than SUN_LEN", )); } for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) { @@ -118,9 +118,9 @@ impl SocketAddr { // linux returns zero bytes of address len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "file descriptor did not correspond to a Unix socket", + &"file descriptor did not correspond to a Unix socket", )); } diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index d1b0ad9e5f847..f25a6280cd076 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -357,17 +357,17 @@ impl FileAttr { tv_nsec: ext.stx_btime.tv_nsec as _, })) } else { - Err(io::Error::new( + Err(io::Error::new_const( io::ErrorKind::Other, - "creation time is not available for the filesystem", + &"creation time is not available for the filesystem", )) }; } } - Err(io::Error::new( + Err(io::Error::new_const( io::ErrorKind::Other, - "creation time is not available on this platform \ + &"creation time is not available on this platform \ currently", )) } @@ -1156,9 +1156,9 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> let reader = File::open(from)?; let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new( + return Err(Error::new_const( ErrorKind::InvalidInput, - "the source path is not an existing regular file", + &"the source path is not an existing regular file", )); } Ok((reader, metadata)) diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index a2912387108e1..d60a4b5591fae 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -1,6 +1,6 @@ macro_rules! unimpl { () => { - return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re.")); + return Err(io::Error::new_const(io::ErrorKind::Other, &"No networking available on L4Re.")); }; } diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 587ffe15981d5..e6b61062d15ff 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -139,9 +139,9 @@ impl Socket { let mut pollfd = libc::pollfd { fd: self.0.raw(), events: libc::POLLOUT, revents: 0 }; if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } @@ -150,7 +150,7 @@ impl Socket { loop { let elapsed = start.elapsed(); if elapsed >= timeout { - return Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")); + return Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")); } let timeout = timeout - elapsed; @@ -177,7 +177,10 @@ impl Socket { // for POLLHUP rather than read readiness if pollfd.revents & libc::POLLHUP != 0 { let e = self.take_error()?.unwrap_or_else(|| { - io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP") + io::Error::new_const( + io::ErrorKind::Other, + &"no error set after POLLHUP", + ) }); return Err(e); } @@ -318,9 +321,9 @@ impl Socket { let timeout = match dur { Some(dur) => { if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index d5e14bec76572..acb889c2cf3c4 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -286,9 +286,9 @@ pub fn current_exe() -> io::Result { 0, ))?; if path_len <= 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::Other, - "KERN_PROC_PATHNAME sysctl returned zero-length string", + &"KERN_PROC_PATHNAME sysctl returned zero-length string", )); } let mut path: Vec = Vec::with_capacity(path_len); @@ -309,9 +309,9 @@ pub fn current_exe() -> io::Result { if curproc_exe.is_file() { return crate::fs::read_link(curproc_exe); } - Err(io::Error::new( + Err(io::Error::new_const( io::ErrorKind::Other, - "/proc/curproc/exe doesn't point to regular file.", + &"/proc/curproc/exe doesn't point to regular file.", )) } sysctl().or_else(|_| procfs()) @@ -328,7 +328,7 @@ pub fn current_exe() -> io::Result { cvt(libc::sysctl(mib, 4, argv.as_mut_ptr() as *mut _, &mut argv_len, ptr::null_mut(), 0))?; argv.set_len(argv_len as usize); if argv[0].is_null() { - return Err(io::Error::new(io::ErrorKind::Other, "no current exe available")); + return Err(io::Error::new_const(io::ErrorKind::Other, &"no current exe available")); } let argv0 = CStr::from_ptr(argv[0]).to_bytes(); if argv0[0] == b'.' || argv0.iter().any(|b| *b == b'/') { @@ -342,9 +342,9 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "linux", target_os = "android", target_os = "emscripten"))] pub fn current_exe() -> io::Result { match crate::fs::read_link("/proc/self/exe") { - Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new( + Err(ref e) if e.kind() == io::ErrorKind::NotFound => Err(io::Error::new_const( io::ErrorKind::Other, - "no /proc/self/exe available. Is /proc mounted?", + &"no /proc/self/exe available. Is /proc mounted?", )), other => other, } @@ -430,7 +430,7 @@ pub fn current_exe() -> io::Result { _get_next_image_info(0, &mut cookie, &mut info, mem::size_of::() as i32); if result != 0 { use crate::io::ErrorKind; - Err(io::Error::new(ErrorKind::Other, "Error getting executable path")) + Err(io::Error::new_const(ErrorKind::Other, &"Error getting executable path")) } else { let name = CStr::from_ptr(info.name.as_ptr()).to_bytes(); Ok(PathBuf::from(OsStr::from_bytes(name))) @@ -446,7 +446,7 @@ pub fn current_exe() -> io::Result { #[cfg(any(target_os = "fuchsia", target_os = "l4re"))] pub fn current_exe() -> io::Result { use crate::io::ErrorKind; - Err(io::Error::new(ErrorKind::Other, "Not yet implemented!")) + Err(io::Error::new_const(ErrorKind::Other, &"Not yet implemented!")) } #[cfg(target_os = "vxworks")] diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 0d4703d7f503a..b19ad4ccdc777 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -22,9 +22,9 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "nul byte found in provided data", + &"nul byte found in provided data", )); } @@ -37,7 +37,10 @@ impl Command { pub fn exec(&mut self, default: Stdio) -> io::Error { if self.saw_nul() { - return io::Error::new(io::ErrorKind::InvalidInput, "nul byte found in provided data"); + return io::Error::new_const( + io::ErrorKind::InvalidInput, + &"nul byte found in provided data", + ); } match self.setup_io(default, true) { @@ -182,9 +185,9 @@ impl Process { ))?; } if actual != 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Failed to get exit status of process", + &"Failed to get exit status of process", )); } Ok(ExitStatus(proc_info.return_code)) @@ -220,9 +223,9 @@ impl Process { ))?; } if actual != 1 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Failed to get exit status of process", + &"Failed to get exit status of process", )); } Ok(Some(ExitStatus(proc_info.return_code))) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 2eb64a99e599a..9cc20ee224c97 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -28,7 +28,10 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + )); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; @@ -118,7 +121,10 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data"); + return io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + ); } match self.setup_io(default, true) { @@ -442,9 +448,9 @@ impl Process { // and used for another process, and we probably shouldn't be killing // random processes, so just return an error. if self.status.is_some() { - Err(Error::new( + Err(Error::new_const( ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", + &"invalid argument: can't kill an exited process", )) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs index 2cdd9c4d19e6e..01e4fd3c994d4 100644 --- a/library/std/src/sys/unsupported/common.rs +++ b/library/std/src/sys/unsupported/common.rs @@ -18,7 +18,7 @@ pub fn unsupported() -> std_io::Result { } pub fn unsupported_err() -> std_io::Error { - std_io::Error::new(std_io::ErrorKind::Other, "operation not supported on this platform") + std_io::Error::new_const(std_io::ErrorKind::Other, &"operation not supported on this platform") } pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind { diff --git a/library/std/src/sys/unsupported/os.rs b/library/std/src/sys/unsupported/os.rs index 0615780c24212..897927e7b79a7 100644 --- a/library/std/src/sys/unsupported/os.rs +++ b/library/std/src/sys/unsupported/os.rs @@ -80,11 +80,11 @@ pub fn getenv(_: &OsStr) -> io::Result> { } pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot set env vars on this platform")) + Err(io::Error::new_const(io::ErrorKind::Other, &"cannot set env vars on this platform")) } pub fn unsetenv(_: &OsStr) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "cannot unset env vars on this platform")) + Err(io::Error::new_const(io::ErrorKind::Other, &"cannot unset env vars on this platform")) } pub fn temp_dir() -> PathBuf { diff --git a/library/std/src/sys/vxworks/process/process_vxworks.rs b/library/std/src/sys/vxworks/process/process_vxworks.rs index 69adbcdddc971..295452327eb70 100644 --- a/library/std/src/sys/vxworks/process/process_vxworks.rs +++ b/library/std/src/sys/vxworks/process/process_vxworks.rs @@ -22,7 +22,10 @@ impl Command { let envp = self.capture_env(); if self.saw_nul() { - return Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")); + return Err(io::Error::new_const( + ErrorKind::InvalidInput, + &"nul byte found in provided data", + )); } let (ours, theirs) = self.setup_io(default, needs_stdin)?; let mut p = Process { pid: 0, status: None }; @@ -134,9 +137,9 @@ impl Process { // and used for another process, and we probably shouldn't be killing // random processes, so just return an error. if self.status.is_some() { - Err(Error::new( + Err(Error::new_const( ErrorKind::InvalidInput, - "invalid argument: can't kill an exited process", + &"invalid argument: can't kill an exited process", )) } else { cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop) diff --git a/library/std/src/sys/wasi/ext/fs.rs b/library/std/src/sys/wasi/ext/fs.rs index 6472642f03499..ba4057bd34ca2 100644 --- a/library/std/src/sys/wasi/ext/fs.rs +++ b/library/std/src/sys/wasi/ext/fs.rs @@ -85,7 +85,7 @@ pub trait FileExt { } } if !buf.is_empty() { - Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer")) + Err(io::Error::new_const(io::ErrorKind::UnexpectedEof, &"failed to fill whole buffer")) } else { Ok(()) } @@ -151,9 +151,9 @@ pub trait FileExt { while !buf.is_empty() { match self.write_at(buf, offset) { Ok(0) => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::WriteZero, - "failed to write whole buffer", + &"failed to write whole buffer", )); } Ok(n) => { @@ -532,5 +532,5 @@ pub fn symlink_path, U: AsRef>(old_path: P, new_path: U) -> } fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) + f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 63c22136273fb..1ec3ff6a10f9a 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -670,7 +670,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { } pub fn osstr2str(f: &OsStr) -> io::Result<&str> { - f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) + f.to_str().ok_or_else(|| io::Error::new_const(io::ErrorKind::Other, &"input must be utf-8")) } pub fn copy(from: &Path, to: &Path) -> io::Result { diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 307a47678c6a2..c6509db80c05b 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -513,9 +513,9 @@ impl File { ) } _ => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::Other, - "Unsupported reparse point type", + &"Unsupported reparse point type", )); } }; @@ -802,7 +802,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { #[cfg(target_vendor = "uwp")] pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { - return Err(io::Error::new(io::ErrorKind::Other, "hard link are not supported on UWP")); + return Err(io::Error::new_const(io::ErrorKind::Other, &"hard link are not supported on UWP")); } pub fn stat(path: &Path) -> io::Result { diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index fcbff59dec007..0353c9811f15f 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -130,9 +130,9 @@ pub fn to_u16s>(s: S) -> crate::io::Result> { fn inner(s: &OsStr) -> crate::io::Result> { let mut maybe_result: Vec = s.encode_wide().collect(); if unrolled_find_u16s(0, &maybe_result).is_some() { - return Err(crate::io::Error::new( + return Err(crate::io::Error::new_const( ErrorKind::InvalidInput, - "strings passed to WinAPI cannot contain NULs", + &"strings passed to WinAPI cannot contain NULs", )); } maybe_result.push(0); diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 9e74454bc2335..e50adcb28a4b7 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -136,9 +136,9 @@ impl Socket { } if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } @@ -164,7 +164,7 @@ impl Socket { unsafe { cvt(c::select(1, ptr::null_mut(), &mut writefds, &mut errorfds, &timeout))? }; match n { - 0 => Err(io::Error::new(io::ErrorKind::TimedOut, "connection timed out")), + 0 => Err(io::Error::new_const(io::ErrorKind::TimedOut, &"connection timed out")), _ => { if writefds.fd_count != 1 { if let Some(e) = self.take_error()? { @@ -339,9 +339,9 @@ impl Socket { Some(dur) => { let timeout = sys::dur2timeout(dur); if timeout == 0 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "cannot set a 0 duration timeout", + &"cannot set a 0 duration timeout", )); } timeout @@ -370,7 +370,7 @@ impl Socket { #[cfg(target_vendor = "uwp")] fn set_no_inherit(&self) -> io::Result<()> { - Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP")) + Err(io::Error::new_const(io::ErrorKind::Other, &"Unavailable on UWP")) } pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 83d37795ee5c1..30bbfdd0dd1e2 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -62,7 +62,7 @@ impl AsRef for EnvKey { fn ensure_no_nuls>(str: T) -> io::Result { if str.as_ref().encode_wide().any(|b| b == 0) { - Err(io::Error::new(ErrorKind::InvalidInput, "nul byte found in provided data")) + Err(io::Error::new_const(ErrorKind::InvalidInput, &"nul byte found in provided data")) } else { Ok(str) } diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs index ff214497166be..be3141e46a1cc 100644 --- a/library/std/src/sys/windows/stdio.rs +++ b/library/std/src/sys/windows/stdio.rs @@ -68,9 +68,9 @@ fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result { let utf8 = match str::from_utf8(&data[..len]) { Ok(s) => s, Err(ref e) if e.valid_up_to() == 0 => { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Windows stdio in console mode does not support writing non-UTF-8 byte sequences", + &"Windows stdio in console mode does not support writing non-UTF-8 byte sequences", )); } Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(), @@ -149,9 +149,9 @@ impl io::Read for Stdin { if buf.len() == 0 { return Ok(0); } else if buf.len() < 4 { - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidInput, - "Windows stdin in console mode does not support a buffer too small to \ + &"Windows stdin in console mode does not support a buffer too small to \ guarantee holding one arbitrary UTF-8 character (4 bytes)", )); } @@ -243,9 +243,9 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result { } Err(_) => { // We can't really do any better than forget all data and return an error. - return Err(io::Error::new( + return Err(io::Error::new_const( io::ErrorKind::InvalidData, - "Windows stdin in console mode does not support non-UTF-16 input; \ + &"Windows stdin in console mode does not support non-UTF-16 input; \ encountered unpaired surrogate", )); } diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs index 6bdb26cd078ed..92d0cc60850c6 100644 --- a/library/std/src/sys_common/fs.rs +++ b/library/std/src/sys_common/fs.rs @@ -9,9 +9,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let metadata = reader.metadata()?; if !metadata.is_file() { - return Err(Error::new( + return Err(Error::new_const( ErrorKind::InvalidInput, - "the source path is not an existing regular file", + &"the source path is not an existing regular file", )); } diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 38ba0d2fbdb6b..d5f29c4a43970 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -108,7 +108,7 @@ pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result *(storage as *const _ as *const c::sockaddr_in6) }))) } - _ => Err(Error::new(ErrorKind::InvalidInput, "invalid argument")), + _ => Err(Error::new_const(ErrorKind::InvalidInput, &"invalid argument")), } } @@ -171,7 +171,7 @@ impl TryFrom<&str> for LookupHost { ($e:expr, $msg:expr) => { match $e { Some(r) => r, - None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)), + None => return Err(io::Error::new_const(io::ErrorKind::InvalidInput, &$msg)), } }; } diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs index 64a5f89890a31..e8cdde8801459 100644 --- a/library/std/src/thread/available_concurrency.rs +++ b/library/std/src/thread/available_concurrency.rs @@ -64,7 +64,7 @@ cfg_if::cfg_if! { sysinfo.dwNumberOfProcessors as usize }; match res { - 0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")), + 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus) }), } } @@ -81,7 +81,7 @@ cfg_if::cfg_if! { fn available_concurrency_internal() -> io::Result { match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { -1 => Err(io::Error::last_os_error()), - 0 => Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")), + 0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")), cpus => Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }), } } @@ -114,7 +114,7 @@ cfg_if::cfg_if! { if res == -1 { return Err(io::Error::last_os_error()); } else if cpus == 0 { - return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")); + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); } } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) @@ -142,7 +142,7 @@ cfg_if::cfg_if! { if res == -1 { return Err(io::Error::last_os_error()); } else if cpus == 0 { - return Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")); + return Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")); } Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) }) @@ -150,7 +150,7 @@ cfg_if::cfg_if! { } else { // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re fn available_concurrency_internal() -> io::Result { - Err(io::Error::new(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform")) + Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")) } } } From 6bbcc5bfbbfd9ba5a6d584a753fa32d80e3a7a17 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 21 Mar 2021 21:44:25 +0100 Subject: [PATCH 05/20] Fix typos Co-authored-by: the8472 --- library/std/src/io/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f4802c32a723f..2122aa755e157 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -264,11 +264,11 @@ impl Error { /// Creates a new I/O error from a known kind of error as well as a /// constant message. /// - /// This function not allocate. + /// This function does not allocate. /// /// This function should maybe change to /// `new_const(kind: ErrorKind)` - /// in the future, when const generics allows that. + /// in the future, when const generics allow that. pub(crate) const fn new_const(kind: ErrorKind, message: &'static &'static str) -> Error { Self { repr: Repr::SimpleMessage(kind, message) } } From 219603a958f2deafd961e746b5ec963c11c44823 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 20 Mar 2021 02:14:04 +0100 Subject: [PATCH 06/20] Only enable assert_dep_graph when query-dep-graph is enabled. --- compiler/rustc_incremental/src/assert_dep_graph.rs | 4 ++++ compiler/rustc_incremental/src/persist/dirty_clean.rs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index f1f69f1510bf1..a080b0ce3395c 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -57,6 +57,10 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { dump_graph(tcx); } + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; + } + // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so // skip the walk. diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 0b544b8ab415e..cb089a728eee0 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -148,6 +148,10 @@ impl Assertion { } pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) { + if !tcx.sess.opts.debugging_opts.query_dep_graph { + return; + } + // can't add `#[rustc_dirty]` etc without opting in to this feature if !tcx.features().rustc_attrs { return; From 45583e56c0d359e9113d64d8eed056863f7ba900 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 22 Mar 2021 12:57:52 -0700 Subject: [PATCH 07/20] Change `-W help` to display edition level. --- compiler/rustc_driver/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 25a78041c0007..e527d55fc2a4f 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -895,7 +895,12 @@ Available lint options: let print_lints = |lints: Vec<&Lint>| { for lint in lints { let name = lint.name_lower().replace("_", "-"); - println!(" {} {:7.7} {}", padded(&name), lint.default_level.as_str(), lint.desc); + println!( + " {} {:7.7} {}", + padded(&name), + lint.default_level(sess.edition()).as_str(), + lint.desc + ); } println!("\n"); }; From 1aad7e738e10e3e1315c219cc3d865fb710fa894 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 22 Mar 2021 19:21:55 +0100 Subject: [PATCH 08/20] Err if the debugging options are not passed. --- compiler/rustc_passes/src/check_attr.rs | 19 ++++++++++++++ src/test/incremental/ich_nested_items.rs | 1 + src/test/incremental/ich_resolve_results.rs | 1 + .../incremental/spans_significant_w_panic.rs | 2 +- src/test/ui/dep-graph/dep-graph-check-attr.rs | 20 ++++++++++++++ .../ui/dep-graph/dep-graph-check-attr.stderr | 26 +++++++++++++++++++ 6 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/dep-graph/dep-graph-check-attr.rs create mode 100644 src/test/ui/dep-graph/dep-graph-check-attr.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d91d0e1765bbf..a86de6fc6f368 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -99,6 +99,12 @@ impl CheckAttrVisitor<'tcx> { self.check_naked(hir_id, attr, span, target) } else if self.tcx.sess.check_name(attr, sym::rustc_legacy_const_generics) { self.check_rustc_legacy_const_generics(&attr, span, target, item) + } else if self.tcx.sess.check_name(attr, sym::rustc_clean) + || self.tcx.sess.check_name(attr, sym::rustc_dirty) + || self.tcx.sess.check_name(attr, sym::rustc_if_this_changed) + || self.tcx.sess.check_name(attr, sym::rustc_then_this_would_need) + { + self.check_rustc_dirty_clean(&attr) } else { // lint-only checks if self.tcx.sess.check_name(attr, sym::cold) { @@ -1012,6 +1018,19 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. + fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool { + if self.tcx.sess.opts.debugging_opts.query_dep_graph { + true + } else { + self.tcx + .sess + .struct_span_err(attr.span, "attribute requires -Z query-dep-graph to be enabled") + .emit(); + false + } + } + /// Checks if `#[link_section]` is applied to a function or static. fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) { match target { diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index aabdaa664112f..4f5f6169f36bf 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -3,6 +3,7 @@ // revisions: cfail1 cfail2 // build-pass (FIXME(62277): could be check-pass?) +// compile-flags: -Z query-dep-graph #![crate_type = "rlib"] #![feature(rustc_attrs)] diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 19df2972f8942..1fb0f8aa84d11 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -2,6 +2,7 @@ // `use` to something different. // revisions: rpass1 rpass2 rpass3 +// compile-flags: -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs index 2574ef5199c86..37728af95164f 100644 --- a/src/test/incremental/spans_significant_w_panic.rs +++ b/src/test/incremental/spans_significant_w_panic.rs @@ -3,7 +3,7 @@ // revisions:rpass1 rpass2 -// compile-flags: -C overflow-checks=on +// compile-flags: -C overflow-checks=on -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.rs b/src/test/ui/dep-graph/dep-graph-check-attr.rs new file mode 100644 index 0000000000000..1026efc1b1dbe --- /dev/null +++ b/src/test/ui/dep-graph/dep-graph-check-attr.rs @@ -0,0 +1,20 @@ +// Test that using rustc_clean/dirty/if_this_changed/then_this_would_need +// are forbidden when `-Z query-dep-graph` is not enabled. + +#![feature(rustc_attrs)] +#![allow(dead_code)] +#![allow(unused_variables)] + +#[rustc_dirty(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +fn main() {} + +#[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +struct Foo { + f: T, +} + +#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph +type TypeAlias = Foo; + +#[rustc_then_this_would_need(variances_of)] //~ ERROR attribute requires -Z query-dep-graph +trait Use {} diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.stderr b/src/test/ui/dep-graph/dep-graph-check-attr.stderr new file mode 100644 index 0000000000000..945a4237c1298 --- /dev/null +++ b/src/test/ui/dep-graph/dep-graph-check-attr.stderr @@ -0,0 +1,26 @@ +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:8:1 + | +LL | #[rustc_dirty(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:11:1 + | +LL | #[rustc_if_this_changed(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:16:1 + | +LL | #[rustc_clean(hir_owner)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: attribute requires -Z query-dep-graph to be enabled + --> $DIR/dep-graph-check-attr.rs:19:1 + | +LL | #[rustc_then_this_would_need(variances_of)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + From f900ee331dfe95493390e1beecb82a277158b60b Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Tue, 23 Mar 2021 02:38:30 +0800 Subject: [PATCH 09/20] Allow not emitting `uwtable` on Android --- compiler/rustc_session/src/session.rs | 2 +- compiler/rustc_target/src/spec/android_base.rs | 5 ++++- compiler/rustc_target/src/spec/mod.rs | 7 +++++++ src/test/codegen/default-requires-uwtable.rs | 15 +++++++++++++++ src/test/codegen/force-no-unwind-tables.rs | 7 +++++++ 5 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 src/test/codegen/default-requires-uwtable.rs create mode 100644 src/test/codegen/force-no-unwind-tables.rs diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index fc57b6b8acedf..203af36b05313 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -863,7 +863,7 @@ impl Session { } else if self.target.requires_uwtable { true } else { - self.opts.cg.force_unwind_tables.unwrap_or(false) + self.opts.cg.force_unwind_tables.unwrap_or(self.target.default_uwtable) } } diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs index f6fbe7cd5f622..c7d2f2329ee86 100644 --- a/compiler/rustc_target/src/spec/android_base.rs +++ b/compiler/rustc_target/src/spec/android_base.rs @@ -12,7 +12,10 @@ pub fn opts() -> TargetOptions { base.dwarf_version = Some(2); base.position_independent_executables = true; base.has_elf_tls = false; - base.requires_uwtable = true; + // This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867 + // for context. (At that time, there was no `-C force-unwind-tables`, so the only solution + // was to always emit `uwtable`). + base.default_uwtable = true; base.crt_static_respected = false; base } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c9fffd213d768..ddfd82625221f 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1111,6 +1111,10 @@ pub struct TargetOptions { /// unwinders. pub requires_uwtable: bool, + /// Whether or not to emit `uwtable` attributes on functions if `-C force-unwind-tables` + /// is not specified and `uwtable` is not required on this target. + pub default_uwtable: bool, + /// Whether or not SIMD types are passed by reference in the Rust ABI, /// typically required if a target can be compiled with a mixed set of /// target features. This is `true` by default, and `false` for targets like @@ -1248,6 +1252,7 @@ impl Default for TargetOptions { default_hidden_visibility: false, emit_debug_gdb_scripts: true, requires_uwtable: false, + default_uwtable: false, simd_types_indirect: true, limit_rdylib_exports: true, override_export_symbols: None, @@ -1711,6 +1716,7 @@ impl Target { key!(default_hidden_visibility, bool); key!(emit_debug_gdb_scripts, bool); key!(requires_uwtable, bool); + key!(default_uwtable, bool); key!(simd_types_indirect, bool); key!(limit_rdylib_exports, bool); key!(override_export_symbols, opt_list); @@ -1947,6 +1953,7 @@ impl ToJson for Target { target_option_val!(default_hidden_visibility); target_option_val!(emit_debug_gdb_scripts); target_option_val!(requires_uwtable); + target_option_val!(default_uwtable); target_option_val!(simd_types_indirect); target_option_val!(limit_rdylib_exports); target_option_val!(override_export_symbols); diff --git a/src/test/codegen/default-requires-uwtable.rs b/src/test/codegen/default-requires-uwtable.rs new file mode 100644 index 0000000000000..d4c4200c5d230 --- /dev/null +++ b/src/test/codegen/default-requires-uwtable.rs @@ -0,0 +1,15 @@ +// revisions: WINDOWS ANDROID +// needs-llvm-components: x86 arm +// compile-flags: -C panic=abort +// [WINDOWS] compile-flags: --target=x86_64-pc-windows-msvc +// [ANDROID] compile-flags: --target=armv7-linux-androideabi + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +// CHECK: attributes #{{.*}} uwtable +pub fn foo() {} diff --git a/src/test/codegen/force-no-unwind-tables.rs b/src/test/codegen/force-no-unwind-tables.rs new file mode 100644 index 0000000000000..dc77e6cb70917 --- /dev/null +++ b/src/test/codegen/force-no-unwind-tables.rs @@ -0,0 +1,7 @@ +// compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n +// ignore-windows + +#![crate_type="lib"] + +// CHECK-NOT: attributes #{{.*}} uwtable +pub fn foo() {} From 494e29deeaa9759b71df8183c00abb72a12575d8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 Mar 2021 22:17:21 +0100 Subject: [PATCH 10/20] Fix codeblock tooltip position --- src/librustdoc/html/static/rustdoc.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 4f287cde73b1b..f20619765a9dc 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1346,7 +1346,7 @@ h4 > .notable-traits { to prevent an overlay between the "collapse toggle" and the information tooltip. However, it's not needed with smaller screen width because the doc/code block is always put "one line" below. */ - .information:first-child > .tooltip { + .docblock > .information:first-child > .tooltip { margin-top: 16px; } } From 6c80deb4a5b8e9ec6dcf03e504461ec71eab69f1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 22 Mar 2021 22:17:43 +0100 Subject: [PATCH 11/20] Add GUI test to enforce tooltip position --- .../rustdoc-gui/check_info_sign_position.goml | 9 +++++++++ src/test/rustdoc-gui/lib.rs | 18 ++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 src/test/rustdoc-gui/check_info_sign_position.goml diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml new file mode 100644 index 0000000000000..9aa72a3ad53e7 --- /dev/null +++ b/src/test/rustdoc-gui/check_info_sign_position.goml @@ -0,0 +1,9 @@ +goto: file://|DOC_PATH|/index.html +goto: ./fn.check_list_code_block.html +// If the codeblock is the first element of the docblock, the information tooltip must have +// have some top margin to avoid going over the toggle (the "[+]"). +assert: (".docblock > .information > .compile_fail", { "margin-top": "16px" }) +// Checks that the other codeblocks don't have this top margin. +assert: ("ol > li > .information > .compile_fail", { "margin-top": "0px" }) +assert: ("ol > li > .information > .ignore", { "margin-top": "0px" }) +assert: (".docblock > .information > .ignore", { "margin-top": "0px" }) diff --git a/src/test/rustdoc-gui/lib.rs b/src/test/rustdoc-gui/lib.rs index 15d8dcc6e8444..4c3007e49d93e 100644 --- a/src/test/rustdoc-gui/lib.rs +++ b/src/test/rustdoc-gui/lib.rs @@ -57,16 +57,26 @@ pub trait AnotherOne { fn func3(); } +/// ```compile_fail +/// whatever +/// ``` +/// /// Check for "i" signs in lists! /// /// 1. elem 1 -/// 2.test 1 -/// ```compile_fail -/// fn foo() {} -/// ``` +/// 2. test 1 +/// ```compile_fail +/// fn foo() {} +/// ``` /// 3. elem 3 /// 4. ```ignore (it's a test) /// fn foo() {} /// ``` /// 5. elem 5 +/// +/// Final one: +/// +/// ```ignore (still a test) +/// let x = 12; +/// ``` pub fn check_list_code_block() {} From 72a180e134f2be8b0b390e87189c638f3a20810c Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 22 Mar 2021 18:18:57 -0700 Subject: [PATCH 12/20] rustdoc: Record crate name instead of using `None` --- src/librustdoc/visit_ast.rs | 2 +- .../rustdoc-ui/intra-doc/private-from-crate-level.rs | 6 ++++++ .../intra-doc/private-from-crate-level.stderr | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs create mode 100644 src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b6782fb75df35..11d1bd5f508f3 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, &krate.item.module, - None, + Some(self.cx.tcx.crate_name), ); top_level_module.is_crate = true; // Attach the crate's exported macros to the top-level module. diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs new file mode 100644 index 0000000000000..e429e75b2148f --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.rs @@ -0,0 +1,6 @@ +// check-pass + +//! [my_module] +//~^ WARN public documentation for `private_from_crate_level` links to private item `my_module` + +mod my_module {} diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr new file mode 100644 index 0000000000000..6172cd2e316a2 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr @@ -0,0 +1,11 @@ +warning: public documentation for `private_from_crate_level` links to private item `my_module` + --> $DIR/private-from-crate-level.rs:3:6 + | +LL | //! [my_module] + | ^^^^^^^^^ this item is private + | + = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default + = note: this link will resolve properly if you pass `--document-private-items` + +warning: 1 warning emitted + From c9ae35978c8520227b360830ff6971f2887c98a2 Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 22 Mar 2021 21:18:06 -0700 Subject: [PATCH 13/20] Don't push the crate name onto the `Cache.stack` Now that we record the crate's name in its `clean::Item`, pushing the crate name onto the `stack` causes duplicate paths. E.g., the URL generated for the path `::foo::bar::baz` would be something like ../foo/foo/bar/baz With this commit, the URL is corrected to ../foo/bar/baz --- src/librustdoc/formats/cache.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 9415caf8b6f3d..f9a663b38ebdc 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -182,8 +182,6 @@ impl Cache { self.primitive_locations.insert(prim, def_id); } - self.stack.push(krate.name.to_string()); - krate = CacheBuilder { tcx, cache: self, empty_cache: Cache::default() }.fold_crate(krate); for (trait_did, dids, impl_) in self.orphan_trait_impls.drain(..) { From 4fa187f8eaf4915dd67b068408794c5e153fca52 Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Tue, 23 Mar 2021 12:23:45 +0100 Subject: [PATCH 14/20] Slight visual improvements to warning boxes in the docs --- src/librustdoc/html/static/rustdoc.css | 9 +++++++++ src/librustdoc/html/static/themes/dark.css | 4 ++-- src/librustdoc/html/static/themes/light.css | 4 ++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index a65b4ce3a0373..b53eb215d85be 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -858,6 +858,15 @@ body.blur > :not(#help) { font-size: 1.5em; } +/* Black one-pixel outline around emoji shapes */ +.emoji { + text-shadow: + 1px 0 0 black, + -1px 0 0 black, + 0 1px 0 black, + 0 -1px 0 black; +} + .module-item .stab { border-radius: 3px; display: inline-block; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 88ac3252bb4b2..cf2d28bb43feb 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -220,8 +220,8 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } -.stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #2f2f2f; } -.stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #2f2f2f; } +.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; } +.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; } .stab.portability > code { background: none; } #help > div { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 9bc21102aaae6..7bf6793809c90 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -218,8 +218,8 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } -.stab.deprecated { background: #F3DFFF; border-color: #7F0087; } -.stab.portability { background: #C4ECFF; border-color: #7BA5DB; } +.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; } +.stab.portability { background: #F3DFFF; border-color: #b07bdb; } .stab.portability > code { background: none; } #help > div { From 5e81325ca4057bf6b40f8a366aa95019559f9844 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 12 Mar 2021 12:19:31 +0100 Subject: [PATCH 15/20] Fix sidebar trait items sort --- src/librustdoc/html/render/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 128eac8cb0a51..e72b3f80bc290 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2122,19 +2122,19 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean items: &[clean::Item], before: &str, filter: impl Fn(&clean::Item) -> bool, - write: impl Fn(&mut Buffer, &Symbol), + write: impl Fn(&mut Buffer, String), after: &str, ) { let mut items = items .iter() .filter_map(|m| match m.name { - Some(ref name) if filter(m) => Some(name), + Some(ref name) if filter(m) => Some(name.to_string()), _ => None, }) .collect::>(); if !items.is_empty() { - items.sort(); + items.sort_unstable(); out.push_str(before); for item in items.into_iter() { write(out, item); From 724590395001d3203903fa1a13b08d12ace56304 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 12 Mar 2021 14:25:01 +0100 Subject: [PATCH 16/20] Add test to enforce sidebar trait items order --- src/test/rustdoc-gui/lib.rs | 9 +++++++-- src/test/rustdoc-gui/trait-sidebar-item-order.goml | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc-gui/trait-sidebar-item-order.goml diff --git a/src/test/rustdoc-gui/lib.rs b/src/test/rustdoc-gui/lib.rs index 15d8dcc6e8444..c5d9f0c5a6806 100644 --- a/src/test/rustdoc-gui/lib.rs +++ b/src/test/rustdoc-gui/lib.rs @@ -47,14 +47,19 @@ pub fn some_more_function(t: &T) -> String { /// Woohoo! A trait! pub trait AnotherOne { + /// Some func 3. + fn func3(); + /// Some func 1. fn func1(); + fn another(); + fn why_not(); + /// Some func 2. fn func2(); - /// Some func 3. - fn func3(); + fn hello(); } /// Check for "i" signs in lists! diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml new file mode 100644 index 0000000000000..914486e1c281d --- /dev/null +++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml @@ -0,0 +1,7 @@ +goto: file://|DOC_PATH|/trait.AnotherOne.html +assert: (".sidebar-links a:nth-of-type(1)", "another") +assert: (".sidebar-links a:nth-of-type(2)", "func1") +assert: (".sidebar-links a:nth-of-type(3)", "func2") +assert: (".sidebar-links a:nth-of-type(4)", "func3") +assert: (".sidebar-links a:nth-of-type(5)", "hello") +assert: (".sidebar-links a:nth-of-type(6)", "why_not") From 801ee834654c2c30e27b4e37da6c7bcab05de6a3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 23 Mar 2021 17:36:36 +0100 Subject: [PATCH 17/20] Use &str instead of String --- src/librustdoc/html/render/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index e72b3f80bc290..05d30187aa853 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2122,13 +2122,13 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean items: &[clean::Item], before: &str, filter: impl Fn(&clean::Item) -> bool, - write: impl Fn(&mut Buffer, String), + write: impl Fn(&mut Buffer, &str), after: &str, ) { let mut items = items .iter() .filter_map(|m| match m.name { - Some(ref name) if filter(m) => Some(name.to_string()), + Some(ref name) if filter(m) => Some(name.as_str()), _ => None, }) .collect::>(); @@ -2137,7 +2137,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean items.sort_unstable(); out.push_str(before); for item in items.into_iter() { - write(out, item); + write(out, &item); } out.push_str(after); } From 31447f6f087e2654d2927f04488303500bec3280 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 23 Mar 2021 12:59:53 +0100 Subject: [PATCH 18/20] Fix comment. --- compiler/rustc_passes/src/check_attr.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a86de6fc6f368..85add83f88bf7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1018,7 +1018,8 @@ impl CheckAttrVisitor<'tcx> { } } - /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. + /// Checks that the dep-graph debugging attributes are only present when the query-dep-graph + /// option is passed to the compiler. fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool { if self.tcx.sess.opts.debugging_opts.query_dep_graph { true From 68244fc521c91b5daba347a4160a884eab268e08 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 23 Mar 2021 11:04:09 -0700 Subject: [PATCH 19/20] Remove unnecessary `Option` wrapping around `Crate.module` I'm wondering if it was originally there so that we could `take` the module which enables `after_krate` to take an `&Crate`. However, the two impls of `after_krate` only use `Crate.name`, so we can pass just the name instead. --- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/clean/utils.rs | 2 +- src/librustdoc/core.rs | 28 +++++------ src/librustdoc/fold.rs | 2 +- src/librustdoc/formats/renderer.rs | 20 +++----- src/librustdoc/html/render/cache.rs | 7 +-- src/librustdoc/html/render/context.rs | 53 +++++++++----------- src/librustdoc/json/mod.rs | 4 +- src/librustdoc/passes/collect_trait_impls.rs | 8 +-- 9 files changed, 54 insertions(+), 72 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 840a42c2b8aab..f03cbaf0b03d5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -51,7 +51,7 @@ thread_local!(crate static MAX_DEF_IDX: RefCell> = crate struct Crate { crate name: Symbol, crate src: FileName, - crate module: Option, + crate module: Item, crate externs: Vec<(CrateNum, ExternalCrate)>, crate primitives: Vec<(DefId, PrimitiveType)>, // These are later on moved into `CACHEKEY`, leaving the map empty. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 6f283d501a4f2..582cbf69ed117 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -76,7 +76,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { Crate { name, src, - module: Some(module), + module, externs, primitives, external_traits: cx.external_traits.clone(), diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c5b5ab0f3d0ac..5a022b2d40c56 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -474,21 +474,19 @@ crate fn run_global_ctxt( let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt)); - if let Some(ref m) = krate.module { - if m.doc_value().map(|d| d.is_empty()).unwrap_or(true) { - let help = "The following guide may be of use:\n\ + if krate.module.doc_value().map(|d| d.is_empty()).unwrap_or(true) { + let help = "The following guide may be of use:\n\ https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html"; - tcx.struct_lint_node( - crate::lint::MISSING_CRATE_LEVEL_DOCS, - DocContext::as_local_hir_id(tcx, m.def_id).unwrap(), - |lint| { - let mut diag = - lint.build("no documentation found for this crate's top-level module"); - diag.help(help); - diag.emit(); - }, - ); - } + tcx.struct_lint_node( + crate::lint::MISSING_CRATE_LEVEL_DOCS, + DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(), + |lint| { + let mut diag = + lint.build("no documentation found for this crate's top-level module"); + diag.help(help); + diag.emit(); + }, + ); } fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) { @@ -531,7 +529,7 @@ crate fn run_global_ctxt( // Process all of the crate attributes, extracting plugin metadata along // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { + for attr in krate.module.attrs.lists(sym::doc) { let diag = ctxt.sess().diagnostic(); let name = attr.name_or_empty(); diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 2b980ebe5926a..376fef6568af7 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -87,7 +87,7 @@ crate trait DocFolder: Sized { } fn fold_crate(&mut self, mut c: Crate) -> Crate { - c.module = c.module.take().and_then(|module| self.fold_item(module)); + c.module = self.fold_item(c.module).unwrap(); { let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) }; diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 9095faf676145..9dcef3a20d6c0 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,5 +1,5 @@ use rustc_middle::ty::TyCtxt; -use rustc_span::edition::Edition; +use rustc_span::{edition::Edition, Symbol}; use crate::clean; use crate::config::RenderOptions; @@ -40,7 +40,7 @@ crate trait FormatRenderer<'tcx>: Sized { /// A handler is available if the renderer wants to report errors. fn after_krate( &mut self, - krate: &clean::Crate, + crate_name: Symbol, diag: &rustc_errors::Handler, ) -> Result<(), Error>; @@ -58,21 +58,15 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( ) -> Result<(), Error> { let prof = &tcx.sess.prof; - let (mut format_renderer, mut krate) = prof + let (mut format_renderer, krate) = prof .extra_verbose_generic_activity("create_renderer", T::descr()) .run(|| T::init(krate, options, edition, cache, tcx))?; - let mut item = match krate.module.take() { - Some(i) => i, - None => return Ok(()), - }; - - item.name = Some(krate.name); - // Render the crate documentation - let mut work = vec![(format_renderer.make_child_renderer(), item)]; + let crate_name = krate.name; + let mut work = vec![(format_renderer.make_child_renderer(), krate.module)]; - let unknown = rustc_span::Symbol::intern(""); + let unknown = Symbol::intern(""); while let Some((mut cx, item)) = work.pop() { if item.is_mod() { // modules are special because they add a namespace. We also need to @@ -102,5 +96,5 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( } } prof.extra_verbose_generic_activity("renderer_after_krate", T::descr()) - .run(|| format_renderer.after_krate(&krate, diag)) + .run(|| format_renderer.after_krate(crate_name, diag)) } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 56fee2c9fec2d..5d49a49472767 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -127,11 +127,8 @@ crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt< crate_items.push(&*item); } - let crate_doc = krate - .module - .as_ref() - .map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s))) - .unwrap_or_default(); + let crate_doc = + krate.module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)); struct CrateData<'a> { doc: String, diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 864fbccbcc451..a18edda5561b1 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::source_map::FileName; -use rustc_span::symbol::sym; +use rustc_span::{symbol::sym, Symbol}; use super::cache::{build_index, ExternalLocation}; use super::print_item::{full_path, item_path, print_item}; @@ -343,29 +343,27 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML - if let Some(attrs) = krate.module.as_ref().map(|m| &m.attrs) { - for attr in attrs.lists(sym::doc) { - match (attr.name_or_empty(), attr.value_str()) { - (sym::html_favicon_url, Some(s)) => { - layout.favicon = s.to_string(); - } - (sym::html_logo_url, Some(s)) => { - layout.logo = s.to_string(); - } - (sym::html_playground_url, Some(s)) => { - playground = Some(markdown::Playground { - crate_name: Some(krate.name.to_string()), - url: s.to_string(), - }); - } - (sym::issue_tracker_base_url, Some(s)) => { - issue_tracker_base_url = Some(s.to_string()); - } - (sym::html_no_source, None) if attr.is_word() => { - include_sources = false; - } - _ => {} + for attr in krate.module.attrs.lists(sym::doc) { + match (attr.name_or_empty(), attr.value_str()) { + (sym::html_favicon_url, Some(s)) => { + layout.favicon = s.to_string(); + } + (sym::html_logo_url, Some(s)) => { + layout.logo = s.to_string(); + } + (sym::html_playground_url, Some(s)) => { + playground = Some(markdown::Playground { + crate_name: Some(krate.name.to_string()), + url: s.to_string(), + }); + } + (sym::issue_tracker_base_url, Some(s)) => { + issue_tracker_base_url = Some(s.to_string()); + } + (sym::html_no_source, None) if attr.is_word() => { + include_sources = false; } + _ => {} } } let (sender, receiver) = channel(); @@ -447,12 +445,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { fn after_krate( &mut self, - krate: &clean::Crate, + crate_name: Symbol, diag: &rustc_errors::Handler, ) -> Result<(), Error> { - let final_file = self.dst.join(&*krate.name.as_str()).join("all.html"); + let final_file = self.dst.join(&*crate_name.as_str()).join("all.html"); let settings_file = self.dst.join("settings.html"); - let crate_name = krate.name; let mut root_path = self.dst.to_str().expect("invalid path").to_owned(); if !root_path.ends_with('/') { @@ -515,9 +512,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if let Some(ref redirections) = self.shared.redirections { if !redirections.borrow().is_empty() { let redirect_map_path = - self.dst.join(&*krate.name.as_str()).join("redirect-map.json"); + self.dst.join(&*crate_name.as_str()).join("redirect-map.json"); let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); - self.shared.ensure_dir(&self.dst.join(&*krate.name.as_str()))?; + self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?; self.shared.fs.write(&redirect_map_path, paths.as_bytes())?; } } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index b762fd7e18bd7..e20147c9d27ae 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -14,7 +14,7 @@ use std::rc::Rc; use rustc_data_structures::fx::FxHashMap; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use rustc_span::edition::Edition; +use rustc_span::{edition::Edition, Symbol}; use rustdoc_json_types as types; @@ -202,7 +202,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn after_krate( &mut self, - _krate: &clean::Crate, + _crate_name: Symbol, _diag: &rustc_errors::Handler, ) -> Result<(), Error> { debug!("Done with crate"); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 685451b87eda9..7b0b2f28fdfff 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -131,12 +131,8 @@ crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate { } } - let items = if let Some(ref mut it) = krate.module { - if let ModuleItem(Module { ref mut items, .. }) = *it.kind { - items - } else { - panic!("collect-trait-impls can't run"); - } + let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind { + items } else { panic!("collect-trait-impls can't run"); }; From a7f902b6934b23504a0716b4f2583d273fd08e2a Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 23 Mar 2021 11:19:42 -0700 Subject: [PATCH 20/20] Remove another unnecessary `Option` The previous changes mean that we can now remove this `Option`. --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctree.rs | 4 ++-- src/librustdoc/visit_ast.rs | 14 ++++---------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 17a961a5f6655..ff30632daabfd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -231,7 +231,7 @@ impl Clean for doctree::Module<'_> { let what_rustc_thinks = Item::from_hir_id_and_parts( self.id, - self.name, + Some(self.name), ModuleItem(Module { is_crate: self.is_crate, items }), cx, ); diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 645b2bb193ec2..189624c0d809c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -5,7 +5,7 @@ use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; crate struct Module<'hir> { - crate name: Option, + crate name: Symbol, crate where_outer: Span, crate where_inner: Span, crate mods: Vec>, @@ -18,7 +18,7 @@ crate struct Module<'hir> { } impl Module<'hir> { - crate fn new(name: Option) -> Module<'hir> { + crate fn new(name: Symbol) -> Module<'hir> { Module { name, id: hir::CRATE_HIR_ID, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 11d1bd5f508f3..17a66d1788e6d 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, &krate.item.module, - Some(self.cx.tcx.crate_name), + self.cx.tcx.crate_name, ); top_level_module.is_crate = true; // Attach the crate's exported macros to the top-level module. @@ -114,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { _ => continue 'exported_macros, }; // Descend into the child module that matches this path segment (if any). - match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) { + match cur_mod.mods.iter_mut().find(|child| child.name == path_segment_ty_ns) { Some(child_mod) => cur_mod = &mut *child_mod, None => continue 'exported_macros, } @@ -133,7 +133,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { vis: &'tcx hir::Visibility<'_>, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, - name: Option, + name: Symbol, ) -> Module<'tcx> { let mut om = Module::new(name); om.where_outer = span; @@ -312,13 +312,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.items.push((item, renamed)) } hir::ItemKind::Mod(ref m) => { - om.mods.push(self.visit_mod_contents( - item.span, - &item.vis, - item.hir_id(), - m, - Some(name), - )); + om.mods.push(self.visit_mod_contents(item.span, &item.vis, item.hir_id(), m, name)); } hir::ItemKind::Fn(..) | hir::ItemKind::ExternCrate(..)