From 35de5c9b35be9feef992c3d03ed95a7176a15726 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 13 Aug 2021 08:58:05 -0700 Subject: [PATCH 01/15] Change WASI's `RawFd` from `u32` to `c_int` (`i32`). WASI previously used `u32` as its `RawFd` type, since its "file descriptors" are unsigned table indices, and there's no fundamental reason why WASI can't have more than 2^31 handles. However, this creates myriad little incompability problems with code that also supports Unix platforms, where `RawFd` is `c_int`. While WASI isn't a Unix, it often shares code with Unix, and this difference made such shared code inconvenient. #87329 is the most recent example of such code. So, switch WASI to use `c_int`, which is `i32`. This will mean that code intending to support WASI should ideally avoid assuming that negative file descriptors are invalid, even though POSIX itself says that file descriptors are never negative. This is a breaking change, but `RawFd` is considerd an experimental feature in [the documentation]. [the documentation]: https://doc.rust-lang.org/stable/std/os/wasi/io/type.RawFd.html --- library/std/src/os/wasi/io.rs | 21 +++++--- library/std/src/sys/wasi/fd.rs | 89 +++++++++++++++++++------------ library/std/src/sys/wasi/fs.rs | 7 +-- library/std/src/sys/wasi/net.rs | 13 ++--- library/std/src/sys/wasi/stdio.rs | 7 +-- 5 files changed, 83 insertions(+), 54 deletions(-) diff --git a/library/std/src/os/wasi/io.rs b/library/std/src/os/wasi/io.rs index cf4501b98cbd4..b6bc74da8e7b5 100644 --- a/library/std/src/os/wasi/io.rs +++ b/library/std/src/os/wasi/io.rs @@ -6,11 +6,18 @@ use crate::fs; use crate::io; use crate::net; +use crate::os::raw; use crate::sys; use crate::sys_common::{AsInner, FromInner, IntoInner}; /// Raw file descriptors. -pub type RawFd = u32; +/// +/// This has type `c_int` to ease compatibility with code that also compiles on +/// Unix configurations, however unlike Unix and POSIX, in WASI negative file +/// descriptors are valid. Only `-1` is reserved for indicating errors. Code +/// intending to be portable across Unix platforms and WASI should avoid +/// assuming that negative file descriptors are invalid. +pub type RawFd = raw::c_int; /// A trait to extract the raw WASI file descriptor from an underlying /// object. @@ -161,41 +168,41 @@ impl IntoRawFd for fs::File { impl AsRawFd for io::Stdin { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl AsRawFd for io::Stdout { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl AsRawFd for io::Stderr { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } impl<'a> AsRawFd for io::StdinLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDIN_FILENO as RawFd + libc::STDIN_FILENO } } impl<'a> AsRawFd for io::StdoutLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDOUT_FILENO as RawFd + libc::STDOUT_FILENO } } impl<'a> AsRawFd for io::StderrLock<'a> { #[inline] fn as_raw_fd(&self) -> RawFd { - libc::STDERR_FILENO as RawFd + libc::STDERR_FILENO } } diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs index ba66eba2ad38b..1f6ea8d6e8df3 100644 --- a/library/std/src/sys/wasi/fd.rs +++ b/library/std/src/sys/wasi/fd.rs @@ -5,10 +5,11 @@ use super::err2io; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::mem; use crate::net::Shutdown; +use crate::os::raw::c_int; #[derive(Debug)] pub struct WasiFd { - fd: wasi::Fd, + fd: c_int, } fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { @@ -26,38 +27,38 @@ fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { } impl WasiFd { - pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd { + pub unsafe fn from_raw(fd: c_int) -> WasiFd { WasiFd { fd } } - pub fn into_raw(self) -> wasi::Fd { + pub fn into_raw(self) -> c_int { let ret = self.fd; mem::forget(self); ret } - pub fn as_raw(&self) -> wasi::Fd { + pub fn as_raw(&self) -> c_int { self.fd } pub fn datasync(&self) -> io::Result<()> { - unsafe { wasi::fd_datasync(self.fd).map_err(err2io) } + unsafe { wasi::fd_datasync(self.fd as wasi::Fd).map_err(err2io) } } pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pread(self.fd as wasi::Fd, iovec(bufs), offset).map_err(err2io) } } pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result { - unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) } + unsafe { wasi::fd_pwrite(self.fd as wasi::Fd, ciovec(bufs), offset).map_err(err2io) } } pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_read(self.fd as wasi::Fd, iovec(bufs)).map_err(err2io) } } pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result { - unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) } + unsafe { wasi::fd_write(self.fd as wasi::Fd, ciovec(bufs)).map_err(err2io) } } pub fn seek(&self, pos: SeekFrom) -> io::Result { @@ -66,37 +67,37 @@ impl WasiFd { SeekFrom::End(pos) => (wasi::WHENCE_END, pos), SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos), }; - unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) } + unsafe { wasi::fd_seek(self.fd as wasi::Fd, offset, whence).map_err(err2io) } } pub fn tell(&self) -> io::Result { - unsafe { wasi::fd_tell(self.fd).map_err(err2io) } + unsafe { wasi::fd_tell(self.fd as wasi::Fd).map_err(err2io) } } // FIXME: __wasi_fd_fdstat_get pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_flags(self.fd as wasi::Fd, flags).map_err(err2io) } } pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> { - unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) } + unsafe { wasi::fd_fdstat_set_rights(self.fd as wasi::Fd, base, inheriting).map_err(err2io) } } pub fn sync(&self) -> io::Result<()> { - unsafe { wasi::fd_sync(self.fd).map_err(err2io) } + unsafe { wasi::fd_sync(self.fd as wasi::Fd).map_err(err2io) } } pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> { - unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) } + unsafe { wasi::fd_advise(self.fd as wasi::Fd, offset, len, advice).map_err(err2io) } } pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> { - unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) } + unsafe { wasi::fd_allocate(self.fd as wasi::Fd, offset, len).map_err(err2io) } } pub fn create_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_create_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn link( @@ -107,7 +108,14 @@ impl WasiFd { new_path: &str, ) -> io::Result<()> { unsafe { - wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io) + wasi::path_link( + self.fd as wasi::Fd, + old_flags, + old_path, + new_fd.fd as wasi::Fd, + new_path, + ) + .map_err(err2io) } } @@ -122,7 +130,7 @@ impl WasiFd { ) -> io::Result { unsafe { wasi::path_open( - self.fd, + self.fd as wasi::Fd, dirflags, path, oflags, @@ -130,25 +138,34 @@ impl WasiFd { fs_rights_inheriting, fs_flags, ) - .map(|fd| WasiFd::from_raw(fd)) + .map(|fd| WasiFd::from_raw(fd as c_int)) .map_err(err2io) } } pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result { - unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) } + unsafe { + wasi::fd_readdir(self.fd as wasi::Fd, buf.as_mut_ptr(), buf.len(), cookie) + .map_err(err2io) + } } pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result { - unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) } + unsafe { + wasi::path_readlink(self.fd as wasi::Fd, path, buf.as_mut_ptr(), buf.len()) + .map_err(err2io) + } } pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) } + unsafe { + wasi::path_rename(self.fd as wasi::Fd, old_path, new_fd.fd as wasi::Fd, new_path) + .map_err(err2io) + } } pub fn filestat_get(&self) -> io::Result { - unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) } + unsafe { wasi::fd_filestat_get(self.fd as wasi::Fd).map_err(err2io) } } pub fn filestat_set_times( @@ -157,11 +174,13 @@ impl WasiFd { mtim: wasi::Timestamp, fstflags: wasi::Fstflags, ) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) } + unsafe { + wasi::fd_filestat_set_times(self.fd as wasi::Fd, atim, mtim, fstflags).map_err(err2io) + } } pub fn filestat_set_size(&self, size: u64) -> io::Result<()> { - unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) } + unsafe { wasi::fd_filestat_set_size(self.fd as wasi::Fd, size).map_err(err2io) } } pub fn path_filestat_get( @@ -169,7 +188,7 @@ impl WasiFd { flags: wasi::Lookupflags, path: &str, ) -> io::Result { - unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) } + unsafe { wasi::path_filestat_get(self.fd as wasi::Fd, flags, path).map_err(err2io) } } pub fn path_filestat_set_times( @@ -181,21 +200,21 @@ impl WasiFd { fstflags: wasi::Fstflags, ) -> io::Result<()> { unsafe { - wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags) + wasi::path_filestat_set_times(self.fd as wasi::Fd, flags, path, atim, mtim, fstflags) .map_err(err2io) } } pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> { - unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) } + unsafe { wasi::path_symlink(old_path, self.fd as wasi::Fd, new_path).map_err(err2io) } } pub fn unlink_file(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) } + unsafe { wasi::path_unlink_file(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn remove_directory(&self, path: &str) -> io::Result<()> { - unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) } + unsafe { wasi::path_remove_directory(self.fd as wasi::Fd, path).map_err(err2io) } } pub fn sock_recv( @@ -203,11 +222,11 @@ impl WasiFd { ri_data: &mut [IoSliceMut<'_>], ri_flags: wasi::Riflags, ) -> io::Result<(usize, wasi::Roflags)> { - unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) } + unsafe { wasi::sock_recv(self.fd as wasi::Fd, iovec(ri_data), ri_flags).map_err(err2io) } } pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result { - unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) } + unsafe { wasi::sock_send(self.fd as wasi::Fd, ciovec(si_data), si_flags).map_err(err2io) } } pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> { @@ -216,7 +235,7 @@ impl WasiFd { Shutdown::Write => wasi::SDFLAGS_WR, Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD, }; - unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) } + unsafe { wasi::sock_shutdown(self.fd as wasi::Fd, how).map_err(err2io) } } } @@ -224,6 +243,6 @@ impl Drop for WasiFd { fn drop(&mut self) { // FIXME: can we handle the return code here even though we can't on // unix? - let _ = unsafe { wasi::fd_close(self.fd) }; + let _ = unsafe { wasi::fd_close(self.fd as wasi::Fd) }; } } diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 8ffa1c88d88e7..55c9c652a8bbb 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -6,6 +6,7 @@ use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; use crate::iter; use crate::mem::{self, ManuallyDrop}; +use crate::os::raw::c_int; use crate::os::wasi::ffi::{OsStrExt, OsStringExt}; use crate::path::{Path, PathBuf}; use crate::ptr; @@ -454,8 +455,8 @@ impl File { } } -impl FromInner for File { - fn from_inner(fd: u32) -> File { +impl FromInner for File { + fn from_inner(fd: c_int) -> File { unsafe { File { fd: WasiFd::from_raw(fd) } } } } @@ -653,7 +654,7 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { let relative = CStr::from_ptr(relative_path).to_bytes().to_vec(); return Ok(( - ManuallyDrop::new(WasiFd::from_raw(fd as u32)), + ManuallyDrop::new(WasiFd::from_raw(fd as c_int)), PathBuf::from(OsString::from_vec(relative)), )); } diff --git a/library/std/src/sys/wasi/net.rs b/library/std/src/sys/wasi/net.rs index 06860673d90e0..50b7352933e57 100644 --- a/library/std/src/sys/wasi/net.rs +++ b/library/std/src/sys/wasi/net.rs @@ -5,6 +5,7 @@ use crate::convert::TryFrom; use crate::fmt; use crate::io::{self, IoSlice, IoSliceMut}; use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr}; +use crate::os::raw::c_int; use crate::sys::unsupported; use crate::sys_common::FromInner; use crate::time::Duration; @@ -115,8 +116,8 @@ impl TcpStream { } } -impl FromInner for TcpStream { - fn from_inner(fd: u32) -> TcpStream { +impl FromInner for TcpStream { + fn from_inner(fd: c_int) -> TcpStream { unsafe { TcpStream { fd: WasiFd::from_raw(fd) } } } } @@ -181,8 +182,8 @@ impl TcpListener { } } -impl FromInner for TcpListener { - fn from_inner(fd: u32) -> TcpListener { +impl FromInner for TcpListener { + fn from_inner(fd: c_int) -> TcpListener { unsafe { TcpListener { fd: WasiFd::from_raw(fd) } } } } @@ -331,8 +332,8 @@ impl UdpSocket { } } -impl FromInner for UdpSocket { - fn from_inner(fd: u32) -> UdpSocket { +impl FromInner for UdpSocket { + fn from_inner(fd: c_int) -> UdpSocket { unsafe { UdpSocket { fd: WasiFd::from_raw(fd) } } } } diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index 209d5b996e5b4..8782f333a1fa4 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -3,6 +3,7 @@ use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; +use crate::os::raw; pub struct Stdin; pub struct Stdout; @@ -14,7 +15,7 @@ impl Stdin { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 0 } } @@ -40,7 +41,7 @@ impl Stdout { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 1 } } @@ -69,7 +70,7 @@ impl Stderr { } #[inline] - pub fn as_raw_fd(&self) -> u32 { + pub fn as_raw_fd(&self) -> raw::c_int { 2 } } From 481b282e8a123364631c0c1a702ae609c878a9a3 Mon Sep 17 00:00:00 2001 From: ibraheemdev Date: Sat, 14 Aug 2021 00:02:02 -0400 Subject: [PATCH 02/15] make `BuildHasher` object safe --- library/core/src/hash/mod.rs | 5 ++++- src/test/ui/build-hasher-object-safe.rs | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/build-hasher-object-safe.rs diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs index 9dbefe0822e36..8dec643255f64 100644 --- a/library/core/src/hash/mod.rs +++ b/library/core/src/hash/mod.rs @@ -520,7 +520,10 @@ pub trait BuildHasher { /// ); /// ``` #[unstable(feature = "build_hasher_simple_hash_one", issue = "86161")] - fn hash_one(&self, x: T) -> u64 { + fn hash_one(&self, x: T) -> u64 + where + Self: Sized, + { let mut hasher = self.build_hasher(); x.hash(&mut hasher); hasher.finish() diff --git a/src/test/ui/build-hasher-object-safe.rs b/src/test/ui/build-hasher-object-safe.rs new file mode 100644 index 0000000000000..50ec8e5e8d96e --- /dev/null +++ b/src/test/ui/build-hasher-object-safe.rs @@ -0,0 +1,10 @@ +// run-pass + +use std::hash::BuildHasher; +use std::collections::hash_map::{DefaultHasher, RandomState}; + +fn ensure_object_safe(_: &dyn BuildHasher) {} + +fn main() { + ensure_object_safe(&RandomState::new()); +} From 2969aece415baa1a42df2a06ba635311000a2b5b Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 14 Aug 2021 21:54:17 +0100 Subject: [PATCH 03/15] Fix dead code warning when inline const is used in pattern --- compiler/rustc_passes/src/dead.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 4e157b0a574fb..ae65222f3f22f 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -15,6 +15,7 @@ use rustc_middle::middle::privacy; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; +use std::mem; // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a @@ -395,8 +396,14 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { } fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + // When inline const blocks are used in pattern position, paths + // referenced by it should be considered as used. + let in_pat = mem::replace(&mut self.in_pat, false); + self.live_symbols.insert(self.tcx.hir().local_def_id(c.hir_id)); intravisit::walk_anon_const(self, c); + + self.in_pat = in_pat; } } From 58f988fa408fb58266c1fbbc62fa29c4473d5e10 Mon Sep 17 00:00:00 2001 From: ibraheemdev Date: Sun, 15 Aug 2021 13:00:25 -0400 Subject: [PATCH 04/15] move object safety test to library/core --- library/core/tests/hash/mod.rs | 9 ++++++++- src/test/ui/build-hasher-object-safe.rs | 10 ---------- 2 files changed, 8 insertions(+), 11 deletions(-) delete mode 100644 src/test/ui/build-hasher-object-safe.rs diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index 1566d35749017..72ccdd4848a47 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -1,7 +1,7 @@ mod sip; use std::default::Default; -use std::hash::{Hash, Hasher}; +use std::hash::{BuildHasher, Hash, Hasher}; use std::rc::Rc; struct MyHasher { @@ -139,3 +139,10 @@ fn test_indirect_hasher() { } assert_eq!(hasher.hash, 5); } + +#[test] +fn test_build_hasher_object_safe() { + use std::collections::hash_map::{DefaultHasher, RandomState}; + + let _: &dyn BuildHasher = &RandomState::new(); +} diff --git a/src/test/ui/build-hasher-object-safe.rs b/src/test/ui/build-hasher-object-safe.rs deleted file mode 100644 index 50ec8e5e8d96e..0000000000000 --- a/src/test/ui/build-hasher-object-safe.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass - -use std::hash::BuildHasher; -use std::collections::hash_map::{DefaultHasher, RandomState}; - -fn ensure_object_safe(_: &dyn BuildHasher) {} - -fn main() { - ensure_object_safe(&RandomState::new()); -} From e62ecdc5a7cbd44a9ade5061ddad4d8a4e1d6599 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 14 Aug 2021 21:56:57 +0100 Subject: [PATCH 05/15] Add a dead code test for using anon const in pattern --- .../ui/lint/dead-code/anon-const-in-pat.rs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/test/ui/lint/dead-code/anon-const-in-pat.rs diff --git a/src/test/ui/lint/dead-code/anon-const-in-pat.rs b/src/test/ui/lint/dead-code/anon-const-in-pat.rs new file mode 100644 index 0000000000000..4c6211a279a58 --- /dev/null +++ b/src/test/ui/lint/dead-code/anon-const-in-pat.rs @@ -0,0 +1,45 @@ +// check-pass +#![feature(inline_const)] +#![allow(incomplete_features)] +#![deny(dead_code)] + +const fn one() -> i32 { + 1 +} + +const fn two() -> i32 { + 2 +} + +const fn three() -> i32 { + 3 +} + +fn inline_const() { + // rust-lang/rust#78171: dead_code lint triggers even though function is used in const pattern + match 1 { + const { one() } => {} + _ => {} + } +} + +fn inline_const_range() { + match 1 { + 1 ..= const { two() } => {} + _ => {} + } +} + +struct S; + +fn const_generic_arg() { + match S::<3> { + S::<{three()}> => {} + } +} + +fn main() { + inline_const(); + inline_const_range(); + const_generic_arg(); +} From 9c21da6ecec2e9668b27647baa2e5ed2dcd462b7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 16 Aug 2021 17:01:33 +0200 Subject: [PATCH 06/15] Take into account jobs number for rustdoc gui tests --- src/bootstrap/test.rs | 2 ++ src/tools/rustdoc-gui/tester.js | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 9effdb2c959d0..d12e86b7c1deb 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -933,6 +933,8 @@ impl Step for RustdocGUI { let mut command = Command::new(&nodejs); command .arg(builder.build.src.join("src/tools/rustdoc-gui/tester.js")) + .arg("--jobs") + .arg(&builder.jobs().to_string()) .arg("--doc-folder") .arg(out_dir.join("doc")) .arg("--tests-folder") diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index 4e77d27d399c2..46b1f68c79a8a 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -17,6 +17,11 @@ function showHelp() { console.log(" --no-headless : disable headless mode"); console.log(" --help : show this message then quit"); console.log(" --tests-folder [PATH] : location of the .GOML tests folder"); + console.log(" --jobs [NUMBER] : number of threads to run tests on"); +} + +function isNumeric(s) { + return /^\d+$/.test(s); } function parseOptions(args) { @@ -27,6 +32,7 @@ function parseOptions(args) { "debug": false, "show_text": false, "no_headless": false, + "jobs": -1, }; var correspondances = { "--doc-folder": "doc_folder", @@ -39,13 +45,21 @@ function parseOptions(args) { for (var i = 0; i < args.length; ++i) { if (args[i] === "--doc-folder" || args[i] === "--tests-folder" - || args[i] === "--file") { + || args[i] === "--file" + || args[i] === "--jobs") { i += 1; if (i >= args.length) { console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } - if (args[i - 1] !== "--file") { + if (args[i - 1] === "--jobs") { + if (!isNumeric(args[i])) { + console.log( + "`--jobs` option expects a positive number, found `" + args[i] + "`"); + return null; + } + opts["jobs"] = parseInt(args[i]); + } else if (args[i - 1] !== "--file") { opts[correspondances[args[i - 1]]] = args[i]; } else { opts["files"].push(args[i]); @@ -153,7 +167,11 @@ async function main(argv) { files.sort(); console.log(`Running ${files.length} rustdoc-gui tests...`); - process.setMaxListeners(files.length + 1); + if (opts["jobs"] < 1) { + process.setMaxListeners(files.length + 1); + } else { + process.setMaxListeners(opts["jobs"]); + } let tests = []; let results = { successful: [], From fdf09130dfb99fc52c1e6ecad6cc9158c65ef08e Mon Sep 17 00:00:00 2001 From: inquisitivecrystal <22333129+inquisitivecrystal@users.noreply.github.com> Date: Tue, 17 Aug 2021 00:09:58 -0700 Subject: [PATCH 07/15] Fix environment variable getter docs --- library/std/src/env.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index f9f14d0dc63b4..a746520095559 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -185,9 +185,13 @@ impl fmt::Debug for VarsOs { /// /// # Errors /// -/// Returns `[None]` if the environment variable isn't set. -/// Returns `[None]` if the environment variable is not valid Unicode. If this is not -/// desired, consider using [`var_os`]. +/// This function will return an error if the environment variable isn't set. +/// +/// This function may return an error if the environment variable's name contains +/// the equal sign character (`=`) or the NUL character. +/// +/// This function will return an error if the environment variable's value is +/// not valid Unicode. If this is not desired, consider using [`var_os`]. /// /// # Examples /// @@ -221,8 +225,13 @@ fn _var(key: &OsStr) -> Result { /// /// # Errors /// -/// Returns `[None]` if the variable isn't set. -/// May return `[None]` if the variable value contains the NUL character. +/// This function returns an error if the environment variable isn't set. +/// +/// This function may return an error if the environment variable's name contains +/// the equal sign character (`=`) or the NUL character. +/// +/// This function may return an error if the environment variable's value contains +/// the NUL character. /// /// # Examples /// From 7ce7fe7176ce156973818e6c80811fe52f0908c6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Aug 2021 14:50:21 +0200 Subject: [PATCH 08/15] Add background-color on clickable definitions in source code --- src/librustdoc/html/static/css/themes/ayu.css | 3 +++ src/librustdoc/html/static/css/themes/dark.css | 3 +++ src/librustdoc/html/static/css/themes/light.css | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 8dd7b2b3edc40..dab6d655c6a87 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -216,6 +216,9 @@ nav.main .separator { a { color: #c5c5c5; } +body.source .example-wrap pre.rust a { + background: #c5c5c5; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index c26122e4bffb5..d9348be6994e2 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -177,6 +177,9 @@ nav.main .separator { a { color: #ddd; } +body.source .example-wrap pre.rust a { + background: #333; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index bc18a72450896..0ffe5929ea593 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -172,6 +172,9 @@ nav.main .separator { a { color: #000; } +body.source .example-wrap pre.rust a { + background: #eee; +} .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short a:not(.srclink):not(.test-arrow), .item-info a, From 907ce72c434950e7d0492e5a1af15d4f9a2b2abd Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Tue, 17 Aug 2021 16:12:11 -0700 Subject: [PATCH 09/15] Expose graphviz modules --- compiler/rustc_mir/src/dataflow/framework/mod.rs | 2 +- compiler/rustc_mir/src/dataflow/mod.rs | 2 +- compiler/rustc_mir/src/util/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir/src/dataflow/framework/mod.rs index 344d7b9becd19..a5badc07d1017 100644 --- a/compiler/rustc_mir/src/dataflow/framework/mod.rs +++ b/compiler/rustc_mir/src/dataflow/framework/mod.rs @@ -42,7 +42,7 @@ mod cursor; mod direction; mod engine; pub mod fmt; -mod graphviz; +pub mod graphviz; pub mod lattice; mod visitor; diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs index 03531a6b0049c..4ca757cf269e4 100644 --- a/compiler/rustc_mir/src/dataflow/mod.rs +++ b/compiler/rustc_mir/src/dataflow/mod.rs @@ -5,7 +5,7 @@ use rustc_span::symbol::{sym, Symbol}; pub(crate) use self::drop_flag_effects::*; pub use self::framework::{ - fmt, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, + fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState, BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects, }; diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs index b7b702431bc2a..3e466b5060feb 100644 --- a/compiler/rustc_mir/src/util/mod.rs +++ b/compiler/rustc_mir/src/util/mod.rs @@ -18,4 +18,4 @@ pub use self::alignment::is_disaligned; pub use self::find_self_call::find_self_call; pub use self::generic_graph::graphviz_safe_def_name; pub use self::graphviz::write_mir_graphviz; -pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; +pub use self::pretty::{dump_enabled, dump_mir, write_mir_fn, write_mir_pretty, PassWhere}; From 0ce96bdcfad27bcfc171afe37b105e02cd82cf61 Mon Sep 17 00:00:00 2001 From: Will Crichton Date: Tue, 17 Aug 2021 20:55:15 -0700 Subject: [PATCH 10/15] Fix bug in fmt_diff_with --- compiler/rustc_mir/src/dataflow/framework/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/dataflow/framework/fmt.rs b/compiler/rustc_mir/src/dataflow/framework/fmt.rs index 0140a75054433..35115ca9db756 100644 --- a/compiler/rustc_mir/src/dataflow/framework/fmt.rs +++ b/compiler/rustc_mir/src/dataflow/framework/fmt.rs @@ -33,7 +33,7 @@ pub trait DebugWithContext: Eq + fmt::Debug { } write!(f, "\u{001f}-")?; - self.fmt_with(ctxt, f) + old.fmt_with(ctxt, f) } } From 14add46e94aa57d6f659ccfb5401e00ffacddc0b Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Thu, 12 Aug 2021 18:54:29 +0000 Subject: [PATCH 11/15] Use more accurate spans when proposing adding lifetime to item --- .../rustc_resolve/src/late/diagnostics.rs | 39 +++++++++++++++---- src/test/ui/error-codes/E0106.stderr | 2 +- .../gat-trait-path-generic-type-arg.stderr | 2 +- .../assoc-type.stderr | 2 +- src/test/ui/issues/issue-19707.stderr | 8 ++-- src/test/ui/issues/issue-26638.stderr | 2 +- src/test/ui/issues/issue-30255.stderr | 6 +-- ...urn-type-requires-explicit-lifetime.stderr | 4 +- .../ex1b-return-no-names-if-else.stderr | 2 +- src/test/ui/rfc1623-2.stderr | 4 +- .../fn-missing-lifetime-in-item.stderr | 4 +- src/test/ui/suggestions/issue-84592.stderr | 2 +- src/test/ui/suggestions/issue-86667.stderr | 4 +- .../ui/suggestions/missing-lt-for-hrtb.stderr | 2 +- .../suggestions/return-elided-lifetime.stderr | 12 +++--- .../in-fn-return-illegal.stderr | 2 +- .../underscore-lifetime-binders.stderr | 2 +- 17 files changed, 62 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 7c97a17b45406..ac77ec1be78d4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2076,16 +2076,40 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for param in params { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { if snippet.starts_with('&') && !snippet.starts_with("&'") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[1..]))); - } else if let Some(stripped) = snippet.strip_prefix("&'_ ") { - introduce_suggestion.push((param.span, format!("&'a {}", &stripped))); + let lo = param.span.lo() + BytePos(1); + let span = param.span.with_lo(lo).with_hi(lo); + introduce_suggestion.push((span, "'a ".to_string())); + } else if let Some(_) = snippet.strip_prefix("&'_ ") { + let lo = param.span.lo() + BytePos(1); + let hi = lo + BytePos(2); + let span = param.span.with_lo(lo).with_hi(hi); + introduce_suggestion.push((span, "'a".to_string())); } } } for ((span, _), sugg) in spans_with_counts.iter().copied().zip(suggs.iter()) { - if let Some(sugg) = sugg { - introduce_suggestion.push((span, sugg.to_string())); + match (sugg, self.tcx.sess.source_map().span_to_snippet(span)) { + (Some(sugg), Ok(snippet)) + if snippet.starts_with('&') + && !snippet.starts_with("&'") + && sugg.starts_with("&") => + { + let lo = span.lo() + BytePos(1); + let span = span.with_lo(lo).with_hi(lo); + introduce_suggestion.push((span, sugg[1..].to_string())); + } + (Some(sugg), Ok(snippet)) + if snippet.starts_with("&'_ ") && sugg.starts_with("&") => + { + let lo = span.lo() + BytePos(1); + let hi = lo + BytePos(2); + let span = span.with_lo(lo).with_hi(hi); + introduce_suggestion.push((span, sugg[1..].to_string())); + } + (Some(sugg), _) => { + introduce_suggestion.push((span, sugg.to_string())); + } + _ => {} } } err.multipart_suggestion_with_style( @@ -2159,7 +2183,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for ((span, _), snippet) in spans_with_counts.iter().copied().zip(snippets.iter()) { match snippet.as_deref() { Some("") => spans_suggs.push((span, "'lifetime, ".to_string())), - Some("&") => spans_suggs.push((span, "&'lifetime ".to_string())), + Some("&") => spans_suggs + .push((span.with_lo(span.lo() + BytePos(1)), "'lifetime ".to_string())), _ => {} } } diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index ee9a4733fd95f..fbd77d9670091 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -59,7 +59,7 @@ LL | type MyStr = &str; help: consider introducing a named lifetime parameter | LL | type MyStr<'a> = &'a str; - | ++++ ~~~ + | ++++ ++ error: aborting due to 5 previous errors diff --git a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr index 1594747e54ce9..e82cbf7e8e5ef 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-generic-type-arg.stderr @@ -15,7 +15,7 @@ LL | type F = &[u8]; help: consider introducing a named lifetime parameter | LL | type F<'a, T1> = &'a [u8]; - | +++ ~~~ + | +++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr index b752cde228d52..44955c58889aa 100644 --- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr +++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -7,7 +7,7 @@ LL | type Output = &i32; help: consider introducing a named lifetime parameter | LL | type Output<'a> = &'a i32; - | ++++ ~~~ + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/assoc-type.rs:16:20 diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr index c3e5fcdd63b55..18f69bb57755a 100644 --- a/src/test/ui/issues/issue-19707.stderr +++ b/src/test/ui/issues/issue-19707.stderr @@ -9,11 +9,11 @@ LL | type Foo = fn(&u8, &u8) -> &u8; help: consider making the type lifetime-generic with a new `'a` lifetime | LL | type Foo = for<'a> fn(&'a u8, &'a u8) -> &'a u8; - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | type Foo<'a> = fn(&'a u8, &'a u8) -> &'a u8; - | ++++ ~~~~~~ ~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:5:27 @@ -26,11 +26,11 @@ LL | fn bar &u8>(f: &F) {} help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | fn bar Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | fn bar<'a, F: Fn(&'a u8, &'a u8) -> &'a u8>(f: &F) {} - | +++ ~~~~~~ ~~~~~~ ~~~ + | +++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 5784ca9d77f0e..bb7cdcbb100ff 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -8,7 +8,7 @@ LL | fn parse_type(iter: Box+'static>) -> &str { iter.ne help: consider introducing a named lifetime parameter | LL | fn parse_type<'a>(iter: Box+'static>) -> &'a str { iter.next() } - | ++++ ~~~ + | ++++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:4:40 diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr index 390aa31487a87..e5f492af5b366 100644 --- a/src/test/ui/issues/issue-30255.stderr +++ b/src/test/ui/issues/issue-30255.stderr @@ -8,7 +8,7 @@ LL | fn f(a: &S, b: i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn f<'a>(a: &'a S, b: i32) -> &'a i32 { - | ++++ ~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:14:34 @@ -20,7 +20,7 @@ LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn g<'a>(a: &'a S, b: bool, c: &'a i32) -> &'a i32 { - | ++++ ~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:19:44 @@ -32,7 +32,7 @@ LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn h<'a>(a: &'a bool, b: bool, c: &'a S, d: &'a i32) -> &'a i32 { - | ++++ ~~~~~~~~ ~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ ++ error: aborting due to 3 previous errors diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index d0dc3601202f0..0e69cd50f6a82 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -20,7 +20,7 @@ LL | fn g(_x: &isize, _y: &isize) -> &isize { help: consider introducing a named lifetime parameter | LL | fn g<'a>(_x: &'a isize, _y: &'a isize) -> &'a isize { - | ++++ ~~~~~~~~~ ~~~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 @@ -32,7 +32,7 @@ LL | fn h(_x: &Foo) -> &isize { help: consider introducing a named lifetime parameter | LL | fn h<'a>(_x: &'a Foo) -> &'a isize { - | ++++ ~~~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index cf365af99040a..bcc3e9510ac97 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -8,7 +8,7 @@ LL | fn foo(x: &i32, y: &i32) -> &i32 { help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error: aborting due to previous error diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr index 8ed606cf90510..65b9f68817aa4 100644 --- a/src/test/ui/rfc1623-2.stderr +++ b/src/test/ui/rfc1623-2.stderr @@ -9,7 +9,7 @@ LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = help: consider making the type lifetime-generic with a new `'a` lifetime | LL | static NON_ELIDABLE_FN: &for<'a> fn(&'a u8, &'a u8) -> &'a u8 = - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/rfc1623-2.rs:10:39 @@ -22,7 +22,7 @@ LL | &(non_elidable as fn(&u8, &u8) -> &u8); help: consider making the type lifetime-generic with a new `'a` lifetime | LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); - | +++++++ ~~~~~~ ~~~~~~ ~~~ + | +++++++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr index 20468cef20ba2..7c0f8d199a965 100644 --- a/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr +++ b/src/test/ui/suggestions/fn-missing-lifetime-in-item.stderr @@ -25,11 +25,11 @@ LL | struct S2 &i32>(F); help: consider making the bound lifetime-generic with a new `'a` lifetime | LL | struct S2 Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++++++ ~~~~~~~ ~~~~~~~ ~~~ + | +++++++ ++ ++ ++ help: consider introducing a named lifetime parameter | LL | struct S2<'a, F: Fn(&'a i32, &'a i32) -> &'a i32>(F); - | +++ ~~~~~~~ ~~~~~~~ ~~~ + | +++ ++ ++ ++ error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types --> $DIR/fn-missing-lifetime-in-item.rs:3:40 diff --git a/src/test/ui/suggestions/issue-84592.stderr b/src/test/ui/suggestions/issue-84592.stderr index fe301e41277fc..70c96feb1de4c 100644 --- a/src/test/ui/suggestions/issue-84592.stderr +++ b/src/test/ui/suggestions/issue-84592.stderr @@ -10,7 +10,7 @@ LL | fn two_lifetimes_needed(a: &(), b: &()) -> TwoLifetimes<'_, '_> { help: consider introducing a named lifetime parameter | LL | fn two_lifetimes_needed<'a>(a: &'a (), b: &'a ()) -> TwoLifetimes<'a, 'a> { - | ++++ ~~~~~~ ~~~~~~ ~~ ~~ + | ++++ ++ ++ ~~ ~~ error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-86667.stderr b/src/test/ui/suggestions/issue-86667.stderr index c1319165a7040..14dbbfffb0e62 100644 --- a/src/test/ui/suggestions/issue-86667.stderr +++ b/src/test/ui/suggestions/issue-86667.stderr @@ -8,7 +8,7 @@ LL | async fn a(s1: &str, s2: &str) -> &str { help: consider introducing a named lifetime parameter | LL | async fn a<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/issue-86667.rs:11:29 @@ -20,7 +20,7 @@ LL | fn b(s1: &str, s2: &str) -> &str { help: consider introducing a named lifetime parameter | LL | fn b<'a>(s1: &'a str, s2: &'a str) -> &'a str { - | ++++ ~~~~~~~ ~~~~~~~ ~~~ + | ++++ ++ ++ ++ error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr index b1caaea9aed7b..33f9d092e6ee0 100644 --- a/src/test/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/src/test/ui/suggestions/missing-lt-for-hrtb.stderr @@ -47,7 +47,7 @@ LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X); help: consider using one of the available lifetimes here | LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X); - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/missing-lt-for-hrtb.rs:5:41 diff --git a/src/test/ui/suggestions/return-elided-lifetime.stderr b/src/test/ui/suggestions/return-elided-lifetime.stderr index cdc3f5e85d142..f147b4463e2f2 100644 --- a/src/test/ui/suggestions/return-elided-lifetime.stderr +++ b/src/test/ui/suggestions/return-elided-lifetime.stderr @@ -80,7 +80,7 @@ LL | fn f3(s: &S) -> &i32 { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3<'a>(s: &'a S) -> &'a i32 { loop {} } - | ++++ ~~~~~ ~~~ + | ++++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:21:26 @@ -92,7 +92,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&'a i32, &i32) { loop {} } - | ++++ ~~~~~ ~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:21:32 @@ -104,7 +104,7 @@ LL | fn f3_(s: &S, t: &S) -> (&i32, &i32) { loop {} } help: consider introducing a named lifetime parameter | LL | fn f3_<'a>(s: &'a S, t: &'a S) -> (&i32, &'a i32) { loop {} } - | ++++ ~~~~~ ~~~~~ ~~~ + | ++++ ++ ++ ++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:25:42 @@ -121,7 +121,7 @@ LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &i32 { loop {} } help: consider using one of the available lifetimes here | LL | fn f4<'a, 'b>(a: &'a i32, b: &'b i32) -> &'lifetime i32 { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:27:44 @@ -138,7 +138,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } help: consider using one of the available lifetimes here | LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&'lifetime i32, &i32) { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:27:50 @@ -155,7 +155,7 @@ LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &i32) { loop {} } help: consider using one of the available lifetimes here | LL | fn f4_<'a, 'b>(a: &'a i32, b: &'b i32) -> (&i32, &'lifetime i32) { loop {} } - | ~~~~~~~~~~ + | +++++++++ error[E0106]: missing lifetime specifier --> $DIR/return-elided-lifetime.rs:31:35 diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr index 89d36bfc92662..6a104e8f94b32 100644 --- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -8,7 +8,7 @@ LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &'a u32, y: &'a u32) -> &'a u32 { loop { } } - | ++++ ~~~~~~~ ~~~~~~~ ~~ + | ++++ ++ ++ ~~ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index 4c207bd3e68d8..22bf1fdba326f 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -43,7 +43,7 @@ LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } help: consider introducing a named lifetime parameter | LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } - | ++++ ~~~~~~ ~~~~~~ ~~ + | ++++ ~~ ~~ ~~ error: aborting due to 5 previous errors From dc24f02bc44f4a598e84e76a9269f2a972d6176d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Aug 2021 16:47:35 +0200 Subject: [PATCH 12/15] Fix anchors display in rustdoc --- src/librustdoc/html/static/css/rustdoc.css | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index bbc48f49e63e1..0714de9d565de 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -735,17 +735,21 @@ a { .anchor { display: none; position: absolute; - left: -7px; + left: 0; + background: none !important; } .anchor.field { left: -5px; } .small-section-header > .anchor { - left: -28px; - padding-right: 10px; /* avoid gap that causes hover to disappear */ + left: -15px; + padding-right: 8px; } -.anchor:before { - content: '\2002\00a7\2002'; +h2.small-section-header > .anchor { + padding-right: 6px; +} +.anchor::before { + content: 'ยง'; } .docblock a:not(.srclink):not(.test-arrow):hover, From 12a776b41d4ed9bd645cfd7bfb4eb3f95ffabd97 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Wed, 18 Aug 2021 11:14:33 +0000 Subject: [PATCH 13/15] review comment: reduce duplication --- .../rustc_resolve/src/late/diagnostics.rs | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ac77ec1be78d4..10f74dc1a043c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2073,43 +2073,46 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { continue; } }); + let span_unnamed_borrow = |span: Span| { + let lo = span.lo() + BytePos(1); + span.with_lo(lo).with_hi(lo) + }; + let span_underscore_borrow = |span: Span| { + let lo = span.lo() + BytePos(1); + let hi = lo + BytePos(2); + span.with_lo(lo).with_hi(hi) + }; + let unnamed_borrow = + |snippet: &str| snippet.starts_with('&') && !snippet.starts_with("&'"); for param in params { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { - if snippet.starts_with('&') && !snippet.starts_with("&'") { - let lo = param.span.lo() + BytePos(1); - let span = param.span.with_lo(lo).with_hi(lo); + if unnamed_borrow(&snippet) { + let span = span_unnamed_borrow(param.span); introduce_suggestion.push((span, "'a ".to_string())); - } else if let Some(_) = snippet.strip_prefix("&'_ ") { - let lo = param.span.lo() + BytePos(1); - let hi = lo + BytePos(2); - let span = param.span.with_lo(lo).with_hi(hi); + } else if snippet.starts_with("&'_ ") { + let span = span_underscore_borrow(param.span); introduce_suggestion.push((span, "'a".to_string())); } } } - for ((span, _), sugg) in spans_with_counts.iter().copied().zip(suggs.iter()) { - match (sugg, self.tcx.sess.source_map().span_to_snippet(span)) { - (Some(sugg), Ok(snippet)) - if snippet.starts_with('&') - && !snippet.starts_with("&'") - && sugg.starts_with("&") => - { - let lo = span.lo() + BytePos(1); - let span = span.with_lo(lo).with_hi(lo); + for (span, sugg) in spans_with_counts.iter().copied().zip(suggs.iter()).filter_map( + |((span, _), sugg)| match sugg { + Some(sugg) => Some((span, sugg)), + _ => None, + }, + ) { + match self.tcx.sess.source_map().span_to_snippet(span) { + Ok(snippet) if unnamed_borrow(&snippet) && sugg.starts_with("&") => { + let span = span_unnamed_borrow(span); introduce_suggestion.push((span, sugg[1..].to_string())); } - (Some(sugg), Ok(snippet)) - if snippet.starts_with("&'_ ") && sugg.starts_with("&") => - { - let lo = span.lo() + BytePos(1); - let hi = lo + BytePos(2); - let span = span.with_lo(lo).with_hi(hi); + Ok(snippet) if snippet.starts_with("&'_ ") && sugg.starts_with("&") => { + let span = span_underscore_borrow(span); introduce_suggestion.push((span, sugg[1..].to_string())); } - (Some(sugg), _) => { + _ => { introduce_suggestion.push((span, sugg.to_string())); } - _ => {} } } err.multipart_suggestion_with_style( From dcb97b6b3c2245196c79fddae43d3b91380e66eb Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 18 Aug 2021 09:11:43 -0300 Subject: [PATCH 14/15] Move private_unused.rs test to impl-trait --- .../ui/{type-alias-impl-trait => impl-trait}/private_unused.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{type-alias-impl-trait => impl-trait}/private_unused.rs (100%) diff --git a/src/test/ui/type-alias-impl-trait/private_unused.rs b/src/test/ui/impl-trait/private_unused.rs similarity index 100% rename from src/test/ui/type-alias-impl-trait/private_unused.rs rename to src/test/ui/impl-trait/private_unused.rs From 9349046ed5b7db491830acc3ec63c29ef9d7f5e5 Mon Sep 17 00:00:00 2001 From: Esteban Kuber Date: Wed, 18 Aug 2021 12:00:07 +0000 Subject: [PATCH 15/15] review comment: use newtype to deduplicate logic --- .../rustc_resolve/src/late/diagnostics.rs | 102 ++++++++++++------ 1 file changed, 70 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 10f74dc1a043c..a602a58e51712 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2073,47 +2073,85 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { continue; } }); - let span_unnamed_borrow = |span: Span| { - let lo = span.lo() + BytePos(1); - span.with_lo(lo).with_hi(lo) - }; - let span_underscore_borrow = |span: Span| { - let lo = span.lo() + BytePos(1); - let hi = lo + BytePos(2); - span.with_lo(lo).with_hi(hi) - }; - let unnamed_borrow = - |snippet: &str| snippet.starts_with('&') && !snippet.starts_with("&'"); + + struct Lifetime(Span, String); + impl Lifetime { + fn is_unnamed(&self) -> bool { + self.1.starts_with('&') && !self.1.starts_with("&'") + } + fn is_underscore(&self) -> bool { + self.1.starts_with("&'_ ") + } + fn is_named(&self) -> bool { + self.1.starts_with("&'") + } + fn suggestion(&self, sugg: String) -> Option<(Span, String)> { + Some( + match ( + self.is_unnamed(), + self.is_underscore(), + self.is_named(), + sugg.starts_with("&"), + ) { + (true, _, _, false) => (self.span_unnamed_borrow(), sugg), + (true, _, _, true) => { + (self.span_unnamed_borrow(), sugg[1..].to_string()) + } + (_, true, _, false) => { + (self.span_underscore_borrow(), sugg.trim().to_string()) + } + (_, true, _, true) => { + (self.span_underscore_borrow(), sugg[1..].trim().to_string()) + } + (_, _, true, false) => { + (self.span_named_borrow(), sugg.trim().to_string()) + } + (_, _, true, true) => { + (self.span_named_borrow(), sugg[1..].trim().to_string()) + } + _ => return None, + }, + ) + } + fn span_unnamed_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + self.0.with_lo(lo).with_hi(lo) + } + fn span_named_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + self.0.with_lo(lo) + } + fn span_underscore_borrow(&self) -> Span { + let lo = self.0.lo() + BytePos(1); + let hi = lo + BytePos(2); + self.0.with_lo(lo).with_hi(hi) + } + } + for param in params { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { - if unnamed_borrow(&snippet) { - let span = span_unnamed_borrow(param.span); - introduce_suggestion.push((span, "'a ".to_string())); - } else if snippet.starts_with("&'_ ") { - let span = span_underscore_borrow(param.span); - introduce_suggestion.push((span, "'a".to_string())); + if let Some((span, sugg)) = + Lifetime(param.span, snippet).suggestion("'a ".to_string()) + { + introduce_suggestion.push((span, sugg)); } } } for (span, sugg) in spans_with_counts.iter().copied().zip(suggs.iter()).filter_map( - |((span, _), sugg)| match sugg { - Some(sugg) => Some((span, sugg)), + |((span, _), sugg)| match &sugg { + Some(sugg) => Some((span, sugg.to_string())), _ => None, }, ) { - match self.tcx.sess.source_map().span_to_snippet(span) { - Ok(snippet) if unnamed_borrow(&snippet) && sugg.starts_with("&") => { - let span = span_unnamed_borrow(span); - introduce_suggestion.push((span, sugg[1..].to_string())); - } - Ok(snippet) if snippet.starts_with("&'_ ") && sugg.starts_with("&") => { - let span = span_underscore_borrow(span); - introduce_suggestion.push((span, sugg[1..].to_string())); - } - _ => { - introduce_suggestion.push((span, sugg.to_string())); - } - } + let (span, sugg) = self + .tcx + .sess + .source_map() + .span_to_snippet(span) + .ok() + .and_then(|snippet| Lifetime(span, snippet).suggestion(sugg.clone())) + .unwrap_or((span, sugg)); + introduce_suggestion.push((span, sugg.to_string())); } err.multipart_suggestion_with_style( &msg,