From 07f54d94e608fc29e8aad386831dacee397e2282 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 13 Aug 2021 21:50:46 +0100 Subject: [PATCH 01/29] Use "rustc" for testing Command args "echo" is not an application on Windows so `Command` tests could fail even if that's not what's being tested for. --- library/std/src/process/tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs index bc71c150550a4..094d2efbdd509 100644 --- a/library/std/src/process/tests.rs +++ b/library/std/src/process/tests.rs @@ -297,7 +297,7 @@ fn test_interior_nul_in_progname_is_error() { #[test] fn test_interior_nul_in_arg_is_error() { - match Command::new("echo").arg("has-some-\0\0s-inside").spawn() { + match Command::new("rustc").arg("has-some-\0\0s-inside").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } @@ -305,7 +305,7 @@ fn test_interior_nul_in_arg_is_error() { #[test] fn test_interior_nul_in_args_is_error() { - match Command::new("echo").args(&["has-some-\0\0s-inside"]).spawn() { + match Command::new("rustc").args(&["has-some-\0\0s-inside"]).spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } @@ -313,7 +313,7 @@ fn test_interior_nul_in_args_is_error() { #[test] fn test_interior_nul_in_current_dir_is_error() { - match Command::new("echo").current_dir("has-some-\0\0s-inside").spawn() { + match Command::new("rustc").current_dir("has-some-\0\0s-inside").spawn() { Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput), Ok(_) => panic!(), } From d9a1f9a79c853f7f4678bfe43905ccc7560974bb Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sat, 30 Oct 2021 12:20:50 +0100 Subject: [PATCH 02/29] Windows: Resolve Command program without using the current directory --- library/std/src/sys/windows/c.rs | 2 + library/std/src/sys/windows/path.rs | 24 ++- library/std/src/sys/windows/process.rs | 167 ++++++++++++++++--- library/std/src/sys/windows/process/tests.rs | 52 ++++++ 4 files changed, 216 insertions(+), 29 deletions(-) diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 9dfc8114eb596..50c4547de85f6 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -734,6 +734,7 @@ if #[cfg(not(target_vendor = "uwp"))] { lpSecurityAttributes: LPSECURITY_ATTRIBUTES, ) -> BOOL; pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL; + pub fn GetWindowsDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; } } } @@ -773,6 +774,7 @@ extern "system" { pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); + pub fn GetSystemDirectoryW(lpBuffer: LPWSTR, uSize: UINT) -> UINT; pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; pub fn SetLastError(dwErrCode: DWORD); diff --git a/library/std/src/sys/windows/path.rs b/library/std/src/sys/windows/path.rs index 460c1eff7788d..8a5a5f56aa8fa 100644 --- a/library/std/src/sys/windows/path.rs +++ b/library/std/src/sys/windows/path.rs @@ -1,9 +1,8 @@ use super::{c, fill_utf16_buf, to_u16s}; -use crate::ffi::OsStr; +use crate::ffi::{OsStr, OsString}; use crate::io; use crate::mem; -use crate::path::Path; -use crate::path::Prefix; +use crate::path::{Path, PathBuf, Prefix}; use crate::ptr; #[cfg(test)] @@ -32,6 +31,25 @@ pub fn is_verbatim_sep(b: u8) -> bool { b == b'\\' } +/// Returns true if `path` looks like a lone filename. +pub(crate) fn is_file_name(path: &OsStr) -> bool { + !path.bytes().iter().copied().any(is_sep_byte) +} +pub(crate) fn has_trailing_slash(path: &OsStr) -> bool { + let is_verbatim = path.bytes().starts_with(br"\\?\"); + let is_separator = if is_verbatim { is_verbatim_sep } else { is_sep_byte }; + if let Some(&c) = path.bytes().last() { is_separator(c) } else { false } +} + +/// Appends a suffix to a path. +/// +/// Can be used to append an extension without removing an existing extension. +pub(crate) fn append_suffix(path: PathBuf, suffix: &OsStr) -> PathBuf { + let mut path = OsString::from(path); + path.push(suffix); + path.into() +} + pub fn parse_prefix(path: &OsStr) -> Option> { use Prefix::{DeviceNS, Disk, Verbatim, VerbatimDisk, VerbatimUNC, UNC}; diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index ccff90629a371..66b210ce1bfb3 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -7,24 +7,24 @@ use crate::cmp; use crate::collections::BTreeMap; use crate::convert::{TryFrom, TryInto}; use crate::env; -use crate::env::split_paths; +use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; use crate::fmt; -use crate::fs; use crate::io::{self, Error, ErrorKind}; use crate::mem; use crate::num::NonZeroI32; -use crate::os::windows::ffi::OsStrExt; +use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle}; -use crate::path::Path; +use crate::path::{Path, PathBuf}; use crate::ptr; use crate::sys::c; use crate::sys::c::NonZeroDWORD; -use crate::sys::cvt; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; +use crate::sys::path; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; +use crate::sys::{cvt, to_u16s}; use crate::sys_common::mutex::StaticMutex; use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::sys_common::{AsInner, IntoInner}; @@ -258,31 +258,19 @@ impl Command { needs_stdin: bool, ) -> io::Result<(Process, StdioPipes)> { let maybe_env = self.env.capture_if_changed(); - // To have the spawning semantics of unix/windows stay the same, we need - // to read the *child's* PATH if one is provided. See #15149 for more - // details. - let program = maybe_env.as_ref().and_then(|env| { - if let Some(v) = env.get(&EnvKey::new("PATH")) { - // Split the value and test each path to see if the - // program exists. - for path in split_paths(&v) { - let path = path - .join(self.program.to_str().unwrap()) - .with_extension(env::consts::EXE_EXTENSION); - if fs::metadata(&path).is_ok() { - return Some(path.into_os_string()); - } - } - } - None - }); let mut si = zeroed_startupinfo(); si.cb = mem::size_of::() as c::DWORD; si.dwFlags = c::STARTF_USESTDHANDLES; - let program = program.as_ref().unwrap_or(&self.program); - let mut cmd_str = make_command_line(program, &self.args, self.force_quotes_enabled)?; + let child_paths = if let Some(env) = maybe_env.as_ref() { + env.get(&EnvKey::new("PATH")).map(|s| s.as_os_str()) + } else { + None + }; + let program = resolve_exe(&self.program, child_paths)?; + let mut cmd_str = + make_command_line(program.as_os_str(), &self.args, self.force_quotes_enabled)?; cmd_str.push(0); // add null terminator // stolen from the libuv code. @@ -321,9 +309,10 @@ impl Command { si.hStdOutput = stdout.as_raw_handle(); si.hStdError = stderr.as_raw_handle(); + let program = to_u16s(&program)?; unsafe { cvt(c::CreateProcessW( - ptr::null(), + program.as_ptr(), cmd_str.as_mut_ptr(), ptr::null_mut(), ptr::null_mut(), @@ -361,6 +350,132 @@ impl fmt::Debug for Command { } } +// Resolve `exe_path` to the executable name. +// +// * If the path is simply a file name then use the paths given by `search_paths` to find the executable. +// * Otherwise use the `exe_path` as given. +// +// This function may also append `.exe` to the name. The rationale for doing so is as follows: +// +// It is a very strong convention that Windows executables have the `exe` extension. +// In Rust, it is common to omit this extension. +// Therefore this functions first assumes `.exe` was intended. +// It falls back to the plain file name if a full path is given and the extension is omitted +// or if only a file name is given and it already contains an extension. +fn resolve_exe<'a>(exe_path: &'a OsStr, child_paths: Option<&OsStr>) -> io::Result { + // Early return if there is no filename. + if exe_path.is_empty() || path::has_trailing_slash(exe_path) { + return Err(io::Error::new_const( + io::ErrorKind::InvalidInput, + &"program path has no file name", + )); + } + // Test if the file name has the `exe` extension. + // This does a case-insensitive `ends_with`. + let has_exe_suffix = if exe_path.len() >= EXE_SUFFIX.len() { + exe_path.bytes()[exe_path.len() - EXE_SUFFIX.len()..] + .eq_ignore_ascii_case(EXE_SUFFIX.as_bytes()) + } else { + false + }; + + // If `exe_path` is an absolute path or a sub-path then don't search `PATH` for it. + if !path::is_file_name(exe_path) { + if has_exe_suffix { + // The application name is a path to a `.exe` file. + // Let `CreateProcessW` figure out if it exists or not. + return Ok(exe_path.into()); + } + let mut path = PathBuf::from(exe_path); + + // Append `.exe` if not already there. + path = path::append_suffix(path, EXE_SUFFIX.as_ref()); + if path.try_exists().unwrap_or(false) { + return Ok(path); + } else { + // It's ok to use `set_extension` here because the intent is to + // remove the extension that was just added. + path.set_extension(""); + return Ok(path); + } + } else { + ensure_no_nuls(exe_path)?; + // From the `CreateProcessW` docs: + // > If the file name does not contain an extension, .exe is appended. + // Note that this rule only applies when searching paths. + let has_extension = exe_path.bytes().contains(&b'.'); + + // Search the directories given by `search_paths`. + let result = search_paths(child_paths, |mut path| { + path.push(&exe_path); + if !has_extension { + path.set_extension(EXE_EXTENSION); + } + if let Ok(true) = path.try_exists() { Some(path) } else { None } + }); + if let Some(path) = result { + return Ok(path); + } + } + // If we get here then the executable cannot be found. + Err(io::Error::new_const(io::ErrorKind::NotFound, &"program not found")) +} + +// Calls `f` for every path that should be used to find an executable. +// Returns once `f` returns the path to an executable or all paths have been searched. +fn search_paths(child_paths: Option<&OsStr>, mut f: F) -> Option +where + F: FnMut(PathBuf) -> Option, +{ + // 1. Child paths + // This is for consistency with Rust's historic behaviour. + if let Some(paths) = child_paths { + for path in env::split_paths(paths).filter(|p| !p.as_os_str().is_empty()) { + if let Some(path) = f(path) { + return Some(path); + } + } + } + + // 2. Application path + if let Ok(mut app_path) = env::current_exe() { + app_path.pop(); + if let Some(path) = f(app_path) { + return Some(path); + } + } + + // 3 & 4. System paths + // SAFETY: This uses `fill_utf16_buf` to safely call the OS functions. + unsafe { + if let Ok(Some(path)) = super::fill_utf16_buf( + |buf, size| c::GetSystemDirectoryW(buf, size), + |buf| f(PathBuf::from(OsString::from_wide(buf))), + ) { + return Some(path); + } + #[cfg(not(target_vendor = "uwp"))] + { + if let Ok(Some(path)) = super::fill_utf16_buf( + |buf, size| c::GetWindowsDirectoryW(buf, size), + |buf| f(PathBuf::from(OsString::from_wide(buf))), + ) { + return Some(path); + } + } + } + + // 5. Parent paths + if let Some(parent_paths) = env::var_os("PATH") { + for path in env::split_paths(&parent_paths).filter(|p| !p.as_os_str().is_empty()) { + if let Some(path) = f(path) { + return Some(path); + } + } + } + None +} + impl Stdio { fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option) -> io::Result { match *self { diff --git a/library/std/src/sys/windows/process/tests.rs b/library/std/src/sys/windows/process/tests.rs index 3b65856dcaca6..6c862edc2370a 100644 --- a/library/std/src/sys/windows/process/tests.rs +++ b/library/std/src/sys/windows/process/tests.rs @@ -128,3 +128,55 @@ fn windows_env_unicode_case() { } } } + +// UWP applications run in a restricted environment which means this test may not work. +#[cfg(not(target_vendor = "uwp"))] +#[test] +fn windows_exe_resolver() { + use super::resolve_exe; + use crate::io; + + // Test a full path, with and without the `exe` extension. + let mut current_exe = env::current_exe().unwrap(); + assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + current_exe.set_extension(""); + assert!(resolve_exe(current_exe.as_ref(), None).is_ok()); + + // Test lone file names. + assert!(resolve_exe(OsStr::new("cmd"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + assert!(resolve_exe(OsStr::new("cmd.EXE"), None).is_ok()); + assert!(resolve_exe(OsStr::new("fc"), None).is_ok()); + + // Invalid file names should return InvalidInput. + assert_eq!(resolve_exe(OsStr::new(""), None).unwrap_err().kind(), io::ErrorKind::InvalidInput); + assert_eq!( + resolve_exe(OsStr::new("\0"), None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + // Trailing slash, therefore there's no file name component. + assert_eq!( + resolve_exe(OsStr::new(r"C:\Path\to\"), None).unwrap_err().kind(), + io::ErrorKind::InvalidInput + ); + + /* + Some of the following tests may need to be changed if you are deliberately + changing the behaviour of `resolve_exe`. + */ + + let paths = env::var_os("PATH").unwrap(); + env::set_var("PATH", ""); + + assert_eq!(resolve_exe(OsStr::new("rustc"), None).unwrap_err().kind(), io::ErrorKind::NotFound); + + let child_paths = Some(paths.as_os_str()); + assert!(resolve_exe(OsStr::new("rustc"), child_paths).is_ok()); + + // The resolver looks in system directories even when `PATH` is empty. + assert!(resolve_exe(OsStr::new("cmd.exe"), None).is_ok()); + + // The application's directory is also searched. + let current_exe = env::current_exe().unwrap(); + assert!(resolve_exe(current_exe.file_name().unwrap().as_ref(), None).is_ok()); +} From 7f3ffbc8c22d0084987966b0496a63ce4d6278d5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 28 Oct 2021 10:58:16 -0700 Subject: [PATCH 03/29] std: Get the standard library compiling for wasm64 This commit goes through and updates various `#[cfg]` as appropriate to get the wasm64-unknown-unknown target behaving similarly to the wasm32-unknown-unknown target. Most of this is just updating various conditions for `target_arch = "wasm32"` to also account for `target_arch = "wasm64"` where appropriate. This commit also lists `wasm64` as an allow-listed architecture to not have the `restricted_std` feature enabled, enabling experimentation with `-Z build-std` externally. The main goal of this commit is to enable playing around with `wasm64-unknown-unknown` externally via `-Z build-std` in a way that's similar to the `wasm32-unknown-unknown` target. These targets are effectively the same and only differ in their pointer size, but wasm64 is much newer and has much less ecosystem/library support so it'll still take time to get wasm64 fully-fledged. --- .../src/spec/wasm64_unknown_unknown.rs | 9 ++++---- library/core/src/ffi.rs | 6 +++++ library/panic_abort/src/lib.rs | 3 ++- library/panic_unwind/src/dummy.rs | 4 ++-- library/panic_unwind/src/lib.rs | 1 + library/std/Cargo.toml | 2 +- library/std/build.rs | 1 + library/std/src/sys/common/alloc.rs | 3 ++- library/std/src/sys/mod.rs | 2 +- library/std/src/sys/wasm/alloc.rs | 4 ++-- library/std/src/sys_common/mod.rs | 1 + library/std/src/thread/local.rs | 22 ++++++++++++------- library/std/src/thread/mod.rs | 5 ++++- 13 files changed, 41 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index fb6526c0e7203..7eacbb4364026 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -23,11 +23,10 @@ pub fn target() -> Target { // For now this target just never has an entry symbol no matter the output // type, so unconditionally pass this. clang_args.push("-Wl,--no-entry".to_string()); - options - .pre_link_args - .get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)) - .unwrap() - .push("--no-entry".to_string()); + + let lld_args = options.pre_link_args.get_mut(&LinkerFlavor::Lld(LldFlavor::Wasm)).unwrap(); + lld_args.push("--no-entry".to_string()); + lld_args.push("-mwasm64".to_string()); Target { llvm_target: "wasm64-unknown-unknown".to_string(), diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs index b208ddd4b272f..ea3de680afeda 100644 --- a/library/core/src/ffi.rs +++ b/library/core/src/ffi.rs @@ -63,6 +63,7 @@ impl fmt::Debug for c_void { all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_arch = "wasm32", + target_arch = "wasm64", target_arch = "asmjs", windows ))] @@ -86,6 +87,7 @@ pub struct VaListImpl<'f> { all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_arch = "wasm32", + target_arch = "wasm64", target_arch = "asmjs", windows ))] @@ -186,6 +188,7 @@ pub struct VaList<'a, 'f: 'a> { ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_arch = "wasm32", + target_arch = "wasm64", target_arch = "asmjs", windows ))] @@ -195,6 +198,7 @@ pub struct VaList<'a, 'f: 'a> { any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_arch = "wasm32"), + not(target_arch = "wasm64"), not(target_arch = "asmjs"), not(windows) ))] @@ -207,6 +211,7 @@ pub struct VaList<'a, 'f: 'a> { all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), target_arch = "wasm32", + target_arch = "wasm64", target_arch = "asmjs", windows ))] @@ -228,6 +233,7 @@ impl<'f> VaListImpl<'f> { any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), not(target_arch = "wasm32"), + not(target_arch = "wasm64"), not(target_arch = "asmjs"), not(windows) ))] diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index ac75ce7f22110..d31df0da36435 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -117,7 +117,8 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe pub mod personalities { #[rustc_std_internal_symbol] #[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "emscripten"),), + all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_arch = "wasm64", not(target_os = "emscripten")), all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",), )))] pub extern "C" fn rust_eh_personality() {} diff --git a/library/panic_unwind/src/dummy.rs b/library/panic_unwind/src/dummy.rs index 4667ede2baad5..a4bcd216c60f0 100644 --- a/library/panic_unwind/src/dummy.rs +++ b/library/panic_unwind/src/dummy.rs @@ -1,6 +1,6 @@ -//! Unwinding for *wasm32* target. +//! Unwinding for unsupported target. //! -//! Right now we don't support this, so this is just stubs. +//! Stubs that simply abort for targets that don't support unwinding otherwise. use alloc::boxed::Box; use core::any::Any; diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index b5d0ca2572c93..4815249f7d53e 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -57,6 +57,7 @@ cfg_if::cfg_if! { } else { // Targets that don't support unwinding. // - arch=wasm32 + // - arch=wasm64 // - os=none ("bare metal" targets) // - os=uefi // - os=espidf diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 248ecdf4befce..85658bf9e3c86 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] [dev-dependencies] rand = "0.7" -[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] diff --git a/library/std/build.rs b/library/std/build.rs index cc7184d57f178..43168e77296ab 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -25,6 +25,7 @@ fn main() { || target.contains("haiku") || target.contains("vxworks") || target.contains("wasm32") + || target.contains("wasm64") || target.contains("asmjs") || target.contains("espidf") || target.contains("solid") diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs index 576667c017392..9665d1fa89243 100644 --- a/library/std/src/sys/common/alloc.rs +++ b/library/std/src/sys/common/alloc.rs @@ -24,7 +24,8 @@ pub const MIN_ALIGN: usize = 8; target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64", - target_arch = "riscv64" + target_arch = "riscv64", + target_arch = "wasm64", )))] pub const MIN_ALIGN: usize = 16; diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 8b8be6ebc2f55..38f45fef9180f 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -40,7 +40,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; - } else if #[cfg(target_arch = "wasm32")] { + } else if #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] { mod wasm; pub use self::wasm::*; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs index ef0ca3dd478cc..bf5dc0273c075 100644 --- a/library/std/src/sys/wasm/alloc.rs +++ b/library/std/src/sys/wasm/alloc.rs @@ -1,8 +1,8 @@ -//! This is an implementation of a global allocator on the wasm32 platform when +//! This is an implementation of a global allocator on the wasm platform when //! emscripten is not in use. In that situation there's no actual runtime for us //! to lean on for allocation, so instead we provide our own! //! -//! The wasm32 instruction set has two instructions for getting the current +//! The wasm instruction set has two instructions for getting the current //! amount of memory and growing the amount of memory. These instructions are the //! foundation on which we're able to build an allocator, so we do so! Note that //! the instructions are also pretty "global" and this is the "global" allocator diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 5a5913ebd79a3..0f2a8cd001259 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -41,6 +41,7 @@ cfg_if::cfg_if! { target_os = "hermit", feature = "restricted-std", all(target_arch = "wasm32", not(target_os = "emscripten")), + all(target_arch = "wasm64", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { pub use crate::sys::net; } else { diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index c53290ec0c7d0..37f9cc40be62f 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -172,7 +172,7 @@ macro_rules! __thread_local_inner { // // FIXME(#84224) this should come after the `target_thread_local` // block. - #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] { static mut VAL: $t = $init; Some(&VAL) @@ -181,7 +181,10 @@ macro_rules! __thread_local_inner { // If the platform has support for `#[thread_local]`, use it. #[cfg(all( target_thread_local, - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all( + any(target_arch = "wasm32", target_arch = "wasm64"), + not(target_feature = "atomics"), + )), ))] { // If a dtor isn't needed we can do something "very raw" and @@ -238,7 +241,10 @@ macro_rules! __thread_local_inner { // same implementation as below for os thread locals. #[cfg(all( not(target_thread_local), - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all( + any(target_arch = "wasm32", target_arch = "wasm64"), + not(target_feature = "atomics"), + )), ))] { #[inline] @@ -285,21 +291,21 @@ macro_rules! __thread_local_inner { // The issue of "should enable on Windows sometimes" is #84933 #[cfg_attr(not(windows), inline)] unsafe fn __getit() -> $crate::option::Option<&'static $t> { - #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] + #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = $crate::thread::__StaticLocalKeyInner::new(); #[thread_local] #[cfg(all( target_thread_local, - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); #[cfg(all( not(target_thread_local), - not(all(target_arch = "wasm32", not(target_feature = "atomics"))), + not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -479,10 +485,10 @@ mod lazy { } } -/// On some platforms like wasm32 there's no threads, so no need to generate +/// On some platforms like wasm there's no threads, so no need to generate /// thread locals and we can instead just use plain statics! #[doc(hidden)] -#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] +#[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] pub mod statik { use super::lazy::LazyKeyInner; use crate::fmt; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 2a155ce311731..41f7bf55f227e 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -200,7 +200,10 @@ pub use self::local::fast::Key as __FastLocalKeyInner; #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] +#[cfg(all( + any(target_arch = "wasm32", target_arch = "wasm64"), + not(target_feature = "atomics") +))] #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; From cfb2f98e9e0bfbad2078b6632c1456c528824088 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 28 Oct 2021 11:20:46 -0700 Subject: [PATCH 04/29] Enable WebAssembly features by default on wasm64 These are all stable as-of-now in the WebAssembly specification so any engine which implements wasm64 will surely implement these features as well. --- compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs index 7eacbb4364026..6b7dfbb87d250 100644 --- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs @@ -28,6 +28,11 @@ pub fn target() -> Target { lld_args.push("--no-entry".to_string()); lld_args.push("-mwasm64".to_string()); + // Any engine that implements wasm64 will surely implement the rest of these + // features since they were all merged into the official spec by the time + // wasm64 was designed. + options.features = "+bulk-memory,+mutable-globals,+sign-ext,+nontrapping-fptoint".to_string(); + Target { llvm_target: "wasm64-unknown-unknown".to_string(), pointer_width: 64, From 971638824fd859eb28dbee069ad109fc80e3e5c5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 28 Oct 2021 16:28:21 -0700 Subject: [PATCH 05/29] Use `target_family = "wasm"` --- library/core/src/ffi.rs | 18 ++++++------------ library/panic_abort/src/lib.rs | 3 +-- library/std/Cargo.toml | 2 +- library/std/src/sys/mod.rs | 2 +- library/std/src/sys_common/mod.rs | 3 +-- library/std/src/thread/local.rs | 20 +++++++------------- library/std/src/thread/mod.rs | 5 +---- 7 files changed, 18 insertions(+), 35 deletions(-) diff --git a/library/core/src/ffi.rs b/library/core/src/ffi.rs index ea3de680afeda..9c4cf89b6bc35 100644 --- a/library/core/src/ffi.rs +++ b/library/core/src/ffi.rs @@ -62,8 +62,7 @@ impl fmt::Debug for c_void { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", - target_arch = "wasm64", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -86,8 +85,7 @@ pub struct VaListImpl<'f> { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", - target_arch = "wasm64", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -187,8 +185,7 @@ pub struct VaList<'a, 'f: 'a> { not(target_arch = "x86_64") ), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", - target_arch = "wasm64", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -197,8 +194,7 @@ pub struct VaList<'a, 'f: 'a> { #[cfg(all( any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), - not(target_arch = "wasm32"), - not(target_arch = "wasm64"), + not(target_family = "wasm"), not(target_arch = "asmjs"), not(windows) ))] @@ -210,8 +206,7 @@ pub struct VaList<'a, 'f: 'a> { #[cfg(any( all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")), all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")), - target_arch = "wasm32", - target_arch = "wasm64", + target_family = "wasm", target_arch = "asmjs", windows ))] @@ -232,8 +227,7 @@ impl<'f> VaListImpl<'f> { #[cfg(all( any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))), - not(target_arch = "wasm32"), - not(target_arch = "wasm64"), + not(target_family = "wasm"), not(target_arch = "asmjs"), not(windows) ))] diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index d31df0da36435..dec5e0b2123fc 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -117,8 +117,7 @@ pub unsafe extern "C-unwind" fn __rust_start_panic(_payload: *mut &mut dyn BoxMe pub mod personalities { #[rustc_std_internal_symbol] #[cfg(not(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - all(target_arch = "wasm64", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",), )))] pub extern "C" fn rust_eh_personality() {} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 85658bf9e3c86..752ab185b8ede 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -35,7 +35,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] [dev-dependencies] rand = "0.7" -[target.'cfg(any(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 38f45fef9180f..167c918c94cf9 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -40,7 +40,7 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "wasi")] { mod wasi; pub use self::wasi::*; - } else if #[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))] { + } else if #[cfg(target_family = "wasm")] { mod wasm; pub use self::wasm::*; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 0f2a8cd001259..804727fbc54d1 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -40,8 +40,7 @@ cfg_if::cfg_if! { if #[cfg(any(target_os = "l4re", target_os = "hermit", feature = "restricted-std", - all(target_arch = "wasm32", not(target_os = "emscripten")), - all(target_arch = "wasm64", not(target_os = "emscripten")), + all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))] { pub use crate::sys::net; } else { diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 37f9cc40be62f..da297c9201746 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -172,7 +172,7 @@ macro_rules! __thread_local_inner { // // FIXME(#84224) this should come after the `target_thread_local` // block. - #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] + #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] { static mut VAL: $t = $init; Some(&VAL) @@ -181,10 +181,7 @@ macro_rules! __thread_local_inner { // If the platform has support for `#[thread_local]`, use it. #[cfg(all( target_thread_local, - not(all( - any(target_arch = "wasm32", target_arch = "wasm64"), - not(target_feature = "atomics"), - )), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] { // If a dtor isn't needed we can do something "very raw" and @@ -241,10 +238,7 @@ macro_rules! __thread_local_inner { // same implementation as below for os thread locals. #[cfg(all( not(target_thread_local), - not(all( - any(target_arch = "wasm32", target_arch = "wasm64"), - not(target_feature = "atomics"), - )), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] { #[inline] @@ -291,21 +285,21 @@ macro_rules! __thread_local_inner { // The issue of "should enable on Windows sometimes" is #84933 #[cfg_attr(not(windows), inline)] unsafe fn __getit() -> $crate::option::Option<&'static $t> { - #[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] + #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = $crate::thread::__StaticLocalKeyInner::new(); #[thread_local] #[cfg(all( target_thread_local, - not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__FastLocalKeyInner<$t> = $crate::thread::__FastLocalKeyInner::new(); #[cfg(all( not(target_thread_local), - not(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics"))), + not(all(target_family = "wasm", not(target_feature = "atomics"))), ))] static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); @@ -488,7 +482,7 @@ mod lazy { /// On some platforms like wasm there's no threads, so no need to generate /// thread locals and we can instead just use plain statics! #[doc(hidden)] -#[cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_feature = "atomics")))] +#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] pub mod statik { use super::lazy::LazyKeyInner; use crate::fmt; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 41f7bf55f227e..39b53b51bfa63 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -200,10 +200,7 @@ pub use self::local::fast::Key as __FastLocalKeyInner; #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(all( - any(target_arch = "wasm32", target_arch = "wasm64"), - not(target_feature = "atomics") -))] +#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] #[doc(hidden)] pub use self::local::statik::Key as __StaticLocalKeyInner; From f738abe63b6c351e0ba523a01b05d04fead8acff Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 28 Oct 2021 16:29:23 -0700 Subject: [PATCH 06/29] Update platform support docs --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 6b0c336b3c799..b749d7f0891ce 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -276,7 +276,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL -`wasm64-unknown-unknown` | * | | WebAssembly +`wasm64-unknown-unknown` | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS `x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support From caa9e4a2d0feaee53df67677a190edab95c996af Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 1 Nov 2021 07:11:05 -0700 Subject: [PATCH 07/29] Review comments --- library/panic_unwind/src/lib.rs | 3 +-- library/std/src/sys/wasm/alloc.rs | 2 +- library/std/src/thread/local.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 4815249f7d53e..e5753ccae2d4f 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -56,8 +56,7 @@ cfg_if::cfg_if! { mod real_imp; } else { // Targets that don't support unwinding. - // - arch=wasm32 - // - arch=wasm64 + // - family=wasm // - os=none ("bare metal" targets) // - os=uefi // - os=espidf diff --git a/library/std/src/sys/wasm/alloc.rs b/library/std/src/sys/wasm/alloc.rs index bf5dc0273c075..3223e8941024c 100644 --- a/library/std/src/sys/wasm/alloc.rs +++ b/library/std/src/sys/wasm/alloc.rs @@ -1,4 +1,4 @@ -//! This is an implementation of a global allocator on the wasm platform when +//! This is an implementation of a global allocator on wasm targets when //! emscripten is not in use. In that situation there's no actual runtime for us //! to lean on for allocation, so instead we provide our own! //! diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index da297c9201746..f6898d283fc16 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -479,7 +479,7 @@ mod lazy { } } -/// On some platforms like wasm there's no threads, so no need to generate +/// On some targets like wasm there's no threads, so no need to generate /// thread locals and we can instead just use plain statics! #[doc(hidden)] #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] From d208e1943bd94f0646dbb6fdc1a14d1973bf63a5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 1 Nov 2021 14:16:25 -0700 Subject: [PATCH 08/29] Fix a crash with wasm64 in LLVM This commit works around a crash in LLVM when the `-generate-arange-section` argument is passed to LLVM. An LLVM bug is opened for this and the code in question is also set to continue passing this flag with LLVM 14, assuming that this is fixed by the time LLVM 14 comes out. Otherwise this should work around debuginfo crashes on LLVM 13. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index c3e7e7169a92c..35a3d21036a14 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -75,7 +75,15 @@ unsafe fn configure_llvm(sess: &Session) { if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - if !sess.opts.debugging_opts.no_generate_arange_section { + if !sess.opts.debugging_opts.no_generate_arange_section + // FIXME: An LLVM bug [1] means that if this option is enabled for + // wasm64 then LLVM will crash when generating debuginfo. Assuming + // that this gets fixed in LLVM 14 this condition here is a + // workaround to work with versions of LLVM 13 and prior. + // + // [1]: https://bugs.llvm.org/show_bug.cgi?id=52376 + && (sess.target.arch != "wasm64" || llvm_util::get_version() >= (14, 0, 0)) + { add("-generate-arange-section", false); } From d2a3c24a9582492d98652a7d88140c34e03c717e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 1 Nov 2021 13:44:28 -0700 Subject: [PATCH 09/29] Update more rustc/libtest things for wasm64 * Add wasm64 variants for inline assembly along the same lines as wasm32 * Update a few directives in libtest to check for `target_family` instead of `target_arch` * Update some rustc codegen and typechecks specialized for wasm32 to also work for wasm64. --- compiler/rustc_codegen_llvm/src/asm.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_target/src/asm/mod.rs | 10 +++++++--- compiler/rustc_typeck/src/check/mod.rs | 2 +- library/test/src/console.rs | 2 +- library/test/src/lib.rs | 4 ++-- src/bootstrap/test.rs | 2 +- 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index f128f76958092..02096f4abfa5f 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -320,7 +320,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::S390x => {} InlineAsmArch::SpirV => {} - InlineAsmArch::Wasm32 => {} + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {} InlineAsmArch::Bpf => {} } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 6c74163fb496c..0041a44a4d8b8 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -769,7 +769,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // we like. To ensure that LLVM picks the right instruction we choose // the raw wasm intrinsic functions which avoid LLVM inserting all the // other control flow automatically. - if self.sess().target.arch == "wasm32" { + if self.sess().target.arch.starts_with("wasm32") { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -791,7 +791,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { // see `fptoui` above for why wasm is different here - if self.sess().target.arch == "wasm32" { + if self.sess().target.arch.starts_with("wasm") { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 1afa6f0283670..cbdc76c55e466 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -490,7 +490,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // Wasm statics with custom link sections get special treatment as they // go into custom sections of the wasm executable. - if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if self.tcx.sess.opts.target_triple.triple().starts_with("wasm") { if let Some(section) = attrs.link_section { let section = llvm::LLVMMDStringInContext( self.llcx, diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 99699c50df584..bff132465215e 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -189,6 +189,7 @@ pub enum InlineAsmArch { S390x, SpirV, Wasm32, + Wasm64, Bpf, } @@ -212,6 +213,7 @@ impl FromStr for InlineAsmArch { "s390x" => Ok(Self::S390x), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), + "wasm64" => Ok(Self::Wasm64), "bpf" => Ok(Self::Bpf), _ => Err(()), } @@ -318,7 +320,7 @@ impl InlineAsmReg { InlineAsmArch::SpirV => { Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) } - InlineAsmArch::Wasm32 => { + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) } InlineAsmArch::Bpf => { @@ -529,7 +531,9 @@ impl InlineAsmRegClass { } InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), - InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { + Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?) + } InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), }) } @@ -725,7 +729,7 @@ pub fn allocatable_registers( spirv::fill_reg_map(arch, has_feature, target, &mut map); map } - InlineAsmArch::Wasm32 => { + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { let mut map = wasm::regclass_map(); wasm::fill_reg_map(arch, has_feature, target, &mut map); map diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index d19e99606bcd8..1404a55bcaace 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -537,7 +537,7 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) { // Only restricted on wasm32 target for now - if !tcx.sess.opts.target_triple.triple().starts_with("wasm32") { + if !tcx.sess.opts.target_triple.triple().starts_with("wasm") { return; } diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 11c5ab48ed3e8..9c261e8cc8eff 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -284,7 +284,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu // Prevent the usage of `Instant` in some cases: // - It's currently not supported for wasm targets. // - We disable it for miri because it's not available when isolation is enabled. - let is_instant_supported = !cfg!(target_arch = "wasm32") && !cfg!(miri); + let is_instant_supported = !cfg!(target_family = "wasm") && !cfg!(miri); let start_time = is_instant_supported.then(Instant::now); run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 99d951d8016bb..2516f3452b186 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -470,7 +470,7 @@ pub fn run_test( // Emscripten can catch panics but other wasm targets cannot let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No - && cfg!(target_arch = "wasm32") + && cfg!(target_family = "wasm") && !cfg!(target_os = "emscripten"); if force_ignore || desc.ignore || ignore_because_no_process_support { @@ -519,7 +519,7 @@ pub fn run_test( // If the platform is single-threaded we're just going to run // the test synchronously, regardless of the concurrency // level. - let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_arch = "wasm32"); + let supports_threads = !cfg!(target_os = "emscripten") && !cfg!(target_family = "wasm"); if concurrency == Concurrent::Yes && supports_threads { let cfg = thread::Builder::new().name(name.as_slice().to_owned()); let mut runtest = Arc::new(Mutex::new(Some(runtest))); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 22bf6b8a9d4dc..cb1b0ebf8db4a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1276,7 +1276,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the builder.ensure(native::TestHelpers { target: compiler.host }); // As well as the target, except for plain wasm32, which can't build it - if !target.contains("wasm32") || target.contains("emscripten") { + if !target.contains("wasm") || target.contains("emscripten") { builder.ensure(native::TestHelpers { target }); } From a3b9405ae7bb6ab4e8103b414e75c44598a10fd2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 1 Nov 2021 14:32:55 -0700 Subject: [PATCH 10/29] Use more robust checks in rustc for wasm --- compiler/rustc_codegen_llvm/src/builder.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 2 +- compiler/rustc_typeck/src/check/mod.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 0041a44a4d8b8..ff88302bf7aaf 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -769,7 +769,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // we like. To ensure that LLVM picks the right instruction we choose // the raw wasm intrinsic functions which avoid LLVM inserting all the // other control flow automatically. - if self.sess().target.arch.starts_with("wasm32") { + if self.sess().target.is_like_wasm { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); @@ -791,7 +791,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { // see `fptoui` above for why wasm is different here - if self.sess().target.arch.starts_with("wasm") { + if self.sess().target.is_like_wasm { let src_ty = self.cx.val_ty(val); if self.cx.type_kind(src_ty) != TypeKind::Vector { let float_width = self.cx.float_width(src_ty); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index cbdc76c55e466..b154ced42f0d6 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -490,7 +490,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // Wasm statics with custom link sections get special treatment as they // go into custom sections of the wasm executable. - if self.tcx.sess.opts.target_triple.triple().starts_with("wasm") { + if self.tcx.sess.target.is_like_wasm { if let Some(section) = attrs.link_section { let section = llvm::LLVMMDStringInContext( self.llcx, diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 1404a55bcaace..e7fba3a70ff42 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -536,8 +536,8 @@ fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { } fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: Span) { - // Only restricted on wasm32 target for now - if !tcx.sess.opts.target_triple.triple().starts_with("wasm") { + // Only restricted on wasm target for now + if !tcx.sess.target.is_like_wasm { return; } From 88f1bf73ee8466d07b1e38755de53a70fc292e20 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 2 Nov 2021 07:23:41 -0700 Subject: [PATCH 11/29] Update stdarch/compiler_builtins Brings in some fixes and better support for the wasm64 target. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- library/stdarch | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7cd07e3847282..34a4af96b29c6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -678,9 +678,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.49" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2" +checksum = "b6591c2442ee984e2b264638a8b5e7ae44fd47b32d28e3a08e2e9c3cdb0c2fb0" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 752ab185b8ede..61c729c5e6c2f 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.44" } +compiler_builtins = { version = "0.1.52" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] } diff --git a/library/stdarch b/library/stdarch index 5fdbc476afc81..2eb870662bed8 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 5fdbc476afc81a789806697fc4a2d9d19b8c9993 +Subproject commit 2eb870662bed827c808042a27c5e2ac8225cb0f1 From b5c3f4c5d8d7be29e3e45e3961a9764c54744a8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 2 Nov 2021 11:28:54 -0700 Subject: [PATCH 12/29] Update dlmalloc for libstd This pulls in a fix for wasm64 to work correctly with this dlmalloc --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34a4af96b29c6..41e5352e81711 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1028,9 +1028,9 @@ dependencies = [ [[package]] name = "dlmalloc" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254" +checksum = "96d075454d918d7358fcd2290dcb4c3ae7bc735388dd1b31ccee1426c1106d8a" dependencies = [ "compiler_builtins", "libc", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 61c729c5e6c2f..839e9576ce5ea 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -36,7 +36,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] rand = "0.7" [target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] -dlmalloc = { version = "0.2.1", features = ['rustc-dep-of-std'] } +dlmalloc = { version = "0.2.2", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } From e4b34966184d707ac5e2038e426558211e08ef6d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Nov 2021 07:53:35 -0800 Subject: [PATCH 13/29] Update stdarch/dlmalloc Ensure that they compile with the now-a-feature-is-required logic. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- library/stdarch | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41e5352e81711..28b922cf9137f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1028,9 +1028,9 @@ dependencies = [ [[package]] name = "dlmalloc" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d075454d918d7358fcd2290dcb4c3ae7bc735388dd1b31ccee1426c1106d8a" +checksum = "a6fe28e0bf9357092740362502f5cc7955d8dc125ebda71dec72336c2e15c62e" dependencies = [ "compiler_builtins", "libc", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 839e9576ce5ea..8f43e902a87ed 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -36,7 +36,7 @@ features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] rand = "0.7" [target.'cfg(any(all(target_family = "wasm", not(target_os = "emscripten")), all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] -dlmalloc = { version = "0.2.2", features = ['rustc-dep-of-std'] } +dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } diff --git a/library/stdarch b/library/stdarch index 2eb870662bed8..815d55c610dab 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 2eb870662bed827c808042a27c5e2ac8225cb0f1 +Subproject commit 815d55c610dab39e92e7c83bf5fd4b7a020b4d46 From 9d6f7f7a57402d5a5cf6725c448b4acf3a24ceab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Nov 2021 07:44:42 -0800 Subject: [PATCH 14/29] Add target documentation for wasm64-unknown-unknown --- .../wasm64-unknown-unknown.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md new file mode 100644 index 0000000000000..021b904debd8f --- /dev/null +++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md @@ -0,0 +1,101 @@ +# `wasm64-unknown-unknown` + +**Tier: 3** + +WebAssembly target which uses 64-bit memories, relying on the [memory64] +WebAssembly proposal. + +[memory64]: https://github.com/webassembly/memory64 + +## Target maintainers + +- Alex Crichton, https://github.com/alexcrichton + +## Requirements + +This target is cross-compiled. The target supports `std` in the same manner as +the `wasm32-unknown-unknown` target which is to say that it comes with the +standard library but many I/O functions such as `std::fs` and `std::net` will +simply return error. Additionally I/O operations like `println!` don't actually +do anything and the prints aren't routed anywhere. This is the same as the +`wasm32-unknown-unknown` target. This target comes by default with an allocator, +currently [dlmalloc] which is [ported to rust][dlmalloc-rs]. + +[dlmalloc]: http://gee.cs.oswego.edu/dl/html/malloc.html +[dlmalloc-rs]: https://github.com/alexcrichton/dlmalloc-rs + +The difference of this target with `wasm32-unknown-unknown` is that it's +compiled for 64-bit memories instead of 32-bit memories. This means that `usize` +is 8-bytes large as well as pointers. The tradeoff, though, is that the maximum +memory size is now the full 64-bit address space instead of the 4GB as limited +by the 32-bit address space for `wasm32-unknown-unknown`. + +This target is not a stable target. The [memory64] WebAssembly proposal is stil +in-progress and not standardized. This means that there are not many engines +which implement the `memory64` feature and if they do they're likely behind a +flag, for example: + +* Nodejs - `--experimental-wasm-memory64` +* Wasmtime - `--wasm-features memory64` + +Also note that at this time the `wasm64-unknown-unknown` target assumes the +presence of other merged wasm proposals such as (with their LLVM feature flags): + +* [Bulk memory] - `+bulk-memory` +* Mutable imported globals - `+mutable-globals` +* [Sign-extending operations] - `+sign-ext` +* [Non-trapping fp-to-int operations] - `+nontrapping-fptoint` + +[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md +[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md +[Non-trapping fp-to-int operations]: https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md + +The `wasm64-unknown-unknown` target intends to match the default Clang targets +for its `"C"` ABI, which is likely to be the same as Clang's +`wasm32-unknown-unknown` largely. + +> **Note**: due to the relatively early-days nature of this target when working +> with this target you may encounter LLVM bugs. If an assertion hit or a bug is +> found it's recommended to open an issue either with rust-lang/rust or ideally +> with LLVM itself. + +This target does not support `panic=unwind` at this time. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`, and the target also requires `lld` to be built to work. + +```toml +[build] +target = ["wasm64-unknown-unknown"] + +[rust] +lld = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `std` by using +`build-std` or similar. + +Note that the following `cfg` directives are set for `wasm64-unknown-unknown`: + +* `cfg(target_arch = "wasm64")` +* `cfg(target_family = "wasm")` + +## Testing + +Currently testing is not well supported for `wasm64-unknown-unknown` and the +Rust project doesn't run any tests for this target. Testing support sort of +works but without `println!` it's not the most exciting tests to run. + +## Cross-compilation toolchains and C code + +Compiling Rust code with C code for `wasm64-unknown-unknown` is theoretically +possible, but there are no known toolchains to do this at this time. At the time +of this writing there is no known "libc" for wasm that works with +`wasm64-unknown-unknown`, which means that mixing C & Rust with this target +effectively cannot be done. From 1d74c77b31a1387512d1fe6cfa24e55548c9ff33 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Nov 2021 10:51:30 -0600 Subject: [PATCH 15/29] Update src/doc/rustc/src/platform-support.md Co-authored-by: Josh Triplett --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index b749d7f0891ce..4da3491c58634 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -276,7 +276,7 @@ target | std | host | notes `thumbv7a-pc-windows-msvc` | ? | | `thumbv7a-uwp-windows-msvc` | ✓ | | `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL -`wasm64-unknown-unknown` | ? | | WebAssembly +[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly `x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64 `x86_64-apple-tvos` | * | | x86 64-bit tvOS `x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support From 9a442353f37a9959c2149927382bb8261d980e76 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 9 Nov 2021 11:17:49 -0800 Subject: [PATCH 16/29] Add a missing doc link --- src/doc/rustc/src/SUMMARY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index c251425d1b7ad..69a0304d41d8c 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -16,6 +16,7 @@ - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) + - [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md) - [Target Tier Policy](target-tier-policy.md) - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) From 7dc38369c00380f8ec23f8b3bf4cfc0ea5c94bcf Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 10 Nov 2021 10:47:00 -0800 Subject: [PATCH 17/29] Disable `.debug_aranges` for all wasm targets This follows from discussion on https://bugs.llvm.org/show_bug.cgi?id=52442 where it looks like this section doesn't make sense for wasm targets. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 ++-------- compiler/rustc_target/src/spec/mod.rs | 6 ++++++ compiler/rustc_target/src/spec/wasm_base.rs | 6 ++++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 35a3d21036a14..3393c9baa28e3 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -75,14 +75,8 @@ unsafe fn configure_llvm(sess: &Session) { if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - if !sess.opts.debugging_opts.no_generate_arange_section - // FIXME: An LLVM bug [1] means that if this option is enabled for - // wasm64 then LLVM will crash when generating debuginfo. Assuming - // that this gets fixed in LLVM 14 this condition here is a - // workaround to work with versions of LLVM 13 and prior. - // - // [1]: https://bugs.llvm.org/show_bug.cgi?id=52376 - && (sess.target.arch != "wasm64" || llvm_util::get_version() >= (14, 0, 0)) + if sess.target.generate_arange_section + && !sess.opts.debugging_opts.no_generate_arange_section { add("-generate-arange-section", false); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 69b90bf10fe6a..0771f99853500 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1357,6 +1357,9 @@ pub struct TargetOptions { /// Minimum number of bits in #[repr(C)] enum. Defaults to 32. pub c_enum_min_bits: u64, + + /// Whether or not the DWARF `.debug_aranges` section should be generated. + pub generate_arange_section: bool, } impl Default for TargetOptions { @@ -1462,6 +1465,7 @@ impl Default for TargetOptions { supported_sanitizers: SanitizerSet::empty(), default_adjusted_cabi: None, c_enum_min_bits: 32, + generate_arange_section: true, } } } @@ -2047,6 +2051,7 @@ impl Target { key!(supported_sanitizers, SanitizerSet)?; key!(default_adjusted_cabi, Option)?; key!(c_enum_min_bits, u64); + key!(generate_arange_section, bool); if base.is_builtin { // This can cause unfortunate ICEs later down the line. @@ -2286,6 +2291,7 @@ impl ToJson for Target { target_option_val!(split_debuginfo); target_option_val!(supported_sanitizers); target_option_val!(c_enum_min_bits); + target_option_val!(generate_arange_section); if let Some(abi) = self.default_adjusted_cabi { d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs index 4c954a1e567cc..24e9c62516999 100644 --- a/compiler/rustc_target/src/spec/wasm_base.rs +++ b/compiler/rustc_target/src/spec/wasm_base.rs @@ -128,6 +128,12 @@ pub fn options() -> TargetOptions { // gdb scripts don't work on wasm blobs emit_debug_gdb_scripts: false, + // There's more discussion of this at + // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is + // that this isn't useful for wasm and has tricky issues with + // representation, so this is disabled. + generate_arange_section: false, + ..Default::default() } } From 8d4fbc9a73fa8aaebe76d3606a90d91e2b8e3faa Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 11 Nov 2021 08:35:59 +0900 Subject: [PATCH 18/29] Add `#[inline]`s to `SortedIndexMultiMap` --- .../rustc_data_structures/src/sorted_map/index_map.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index e92db9ea12805..61c7239c55ff4 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -34,39 +34,47 @@ pub struct SortedIndexMultiMap { } impl SortedIndexMultiMap { + #[inline] pub fn new() -> Self { SortedIndexMultiMap { items: IndexVec::new(), idx_sorted_by_item_key: Vec::new() } } + #[inline] pub fn len(&self) -> usize { self.items.len() } + #[inline] pub fn is_empty(&self) -> bool { self.items.is_empty() } /// Returns an iterator over the items in the map in insertion order. + #[inline] pub fn into_iter(self) -> impl DoubleEndedIterator { self.items.into_iter() } /// Returns an iterator over the items in the map in insertion order along with their indices. + #[inline] pub fn into_iter_enumerated(self) -> impl DoubleEndedIterator { self.items.into_iter_enumerated() } /// Returns an iterator over the items in the map in insertion order. + #[inline] pub fn iter(&self) -> impl '_ + DoubleEndedIterator { self.items.iter().map(|(ref k, ref v)| (k, v)) } /// Returns an iterator over the items in the map in insertion order along with their indices. + #[inline] pub fn iter_enumerated(&self) -> impl '_ + DoubleEndedIterator { self.items.iter_enumerated().map(|(i, (ref k, ref v))| (i, (k, v))) } /// Returns the item in the map with the given index. + #[inline] pub fn get(&self, idx: I) -> Option<&(K, V)> { self.items.get(idx) } @@ -75,6 +83,7 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. + #[inline] pub fn get_by_key(&'a self, key: K) -> impl 'a + Iterator { self.get_by_key_enumerated(key).map(|(_, v)| v) } @@ -84,6 +93,7 @@ impl SortedIndexMultiMap { /// /// If there are multiple items that are equivalent to `key`, they will be yielded in /// insertion order. + #[inline] pub fn get_by_key_enumerated(&'a self, key: K) -> impl '_ + Iterator { let lower_bound = self.idx_sorted_by_item_key.partition_point(|&i| self.items[i].0 < key); self.idx_sorted_by_item_key[lower_bound..].iter().map_while(move |&i| { From c15b55ace6ae247fa1ca0001d8840c974644a817 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 10 Nov 2021 19:25:54 +0100 Subject: [PATCH 19/29] Add Vec::retain_mut --- library/alloc/src/vec/mod.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index d52c78eedf3fa..4989244b50e27 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1444,6 +1444,34 @@ impl Vec { pub fn retain(&mut self, mut f: F) where F: FnMut(&T) -> bool, + { + self.retain_mut(|elem| f(elem)); + } + + /// Retains only the elements specified by the predicate, passing a mutable reference to it. + /// + /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. + /// This method operates in place, visiting each element exactly once in the + /// original order, and preserves the order of the retained elements. + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_retain_mut)] + /// + /// let mut vec = vec![1, 2, 3, 4]; + /// vec.retain_mut(|x| if *x > 3 { + /// false + /// } else { + /// *x += 1; + /// true + /// }); + /// assert_eq!(vec, [2, 3, 4]); + /// ``` + #[unstable(feature = "vec_retain_mut", issue = "90829")] + pub fn retain_mut(&mut self, mut f: F) + where + F: FnMut(&mut T) -> bool, { let original_len = self.len(); // Avoid double drop if the drop guard is not executed, @@ -1496,7 +1524,7 @@ impl Vec { g: &mut BackshiftOnDrop<'_, T, A>, ) -> bool where - F: FnMut(&T) -> bool, + F: FnMut(&mut T) -> bool, { // SAFETY: Unchecked element must be valid. let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; From 24acf8602969215469ac26a2c0042385096345d9 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 13 Nov 2021 23:56:22 +0100 Subject: [PATCH 20/29] Fix span for non-satisfied trivial trait bounds The spans for "trait bound not satisfied" errors in trivial trait bounds referenced the entire item (fn, impl, struct) before. Now they only reference the obligation itself (`String: Copy`) Address #90869 --- compiler/rustc_infer/src/traits/util.rs | 17 +++++ .../rustc_trait_selection/src/traits/mod.rs | 3 +- compiler/rustc_typeck/src/check/wfcheck.rs | 25 +++++- .../ui/const-generics/issues/issue-67185-2.rs | 9 +-- .../issues/issue-67185-2.stderr | 60 ++++++--------- src/test/ui/cross/cross-fn-cache-hole.rs | 4 +- src/test/ui/cross/cross-fn-cache-hole.stderr | 12 +-- .../feature-gate-trivial_bounds.stderr | 76 +++++++------------ 8 files changed, 102 insertions(+), 104 deletions(-) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c839f824d1c9c..92f74af4eb3eb 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -5,6 +5,7 @@ use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt, WithConstness}; use rustc_span::symbol::Ident; +use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -97,6 +98,22 @@ pub fn elaborate_predicates<'tcx>( elaborate_obligations(tcx, obligations) } +pub fn elaborate_predicates_with_span<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: impl Iterator, Span)>, +) -> Elaborator<'tcx> { + let obligations = predicates + .map(|(predicate, span)| { + predicate_obligation( + predicate, + ty::ParamEnv::empty(), + ObligationCause::dummy_with_span(span), + ) + }) + .collect(); + elaborate_obligations(tcx, obligations) +} + pub fn elaborate_obligations<'tcx>( tcx: TyCtxt<'tcx>, mut obligations: Vec>, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d4a586b0124a2..91671994c5ace 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -65,7 +65,8 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError} pub use self::structural_match::search_for_structural_match_violation; pub use self::structural_match::NonStructuralMatchTy; pub use self::util::{ - elaborate_obligations, elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs, + elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span, + elaborate_trait_ref, elaborate_trait_refs, }; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{ diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index c1adc2894ccfc..0050ac99cb19a 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1641,19 +1641,38 @@ fn report_bivariance(tcx: TyCtxt<'_>, param: &rustc_hir::GenericParam<'_>) { /// Feature gates RFC 2056 -- trivial bounds, checking for global bounds that /// aren't true. -fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) { +fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, mut span: Span, id: hir::HirId) { let empty_env = ty::ParamEnv::empty(); let def_id = fcx.tcx.hir().local_def_id(id); - let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p); + let predicates_with_span = + fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, span)| (*p, *span)); // Check elaborated bounds. - let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); + let implied_obligations = traits::elaborate_predicates_with_span(fcx.tcx, predicates_with_span); for obligation in implied_obligations { let pred = obligation.predicate; // Match the existing behavior. if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() { let pred = fcx.normalize_associated_types_in(span, pred); + let hir_node = fcx.tcx.hir().find(id); + + // only use the span of the predicate clause (#90869) + + if let Some(hir::Generics { where_clause, .. }) = + hir_node.and_then(|node| node.generics()) + { + let obligation_span = obligation.cause.span(fcx.tcx); + + span = where_clause + .predicates + .iter() + // There seems to be no better way to find out which predicate we are in + .find(|pred| pred.span().contains(obligation_span)) + .map(|pred| pred.span()) + .unwrap_or(obligation_span); + } + let obligation = traits::Obligation::new( traits::ObligationCause::new(span, id, traits::TrivialBound), empty_env, diff --git a/src/test/ui/const-generics/issues/issue-67185-2.rs b/src/test/ui/const-generics/issues/issue-67185-2.rs index c1a04e2014749..18bb6f6bc1edc 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.rs +++ b/src/test/ui/const-generics/issues/issue-67185-2.rs @@ -9,11 +9,10 @@ trait Bar {} impl Bar for [u16; 4] {} impl Bar for [[u16; 3]; 3] {} -trait Foo //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] - //~^ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] - where - [::Quaks; 2]: Bar, - ::Quaks: Bar, +trait Foo +where + [::Quaks; 2]: Bar, //~ ERROR the trait bound `[[u16; 3]; 2]: Bar` is not satisfied [E0277] + ::Quaks: Bar, //~ ERROR the trait bound `[u16; 3]: Bar` is not satisfied [E0277] { } diff --git a/src/test/ui/const-generics/issues/issue-67185-2.stderr b/src/test/ui/const-generics/issues/issue-67185-2.stderr index 7167bea94bbb6..89aa3d395e25b 100644 --- a/src/test/ui/const-generics/issues/issue-67185-2.stderr +++ b/src/test/ui/const-generics/issues/issue-67185-2.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:15:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[u16; 3]` +LL | ::Quaks: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[u16; 3]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -17,16 +11,10 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:12:1 + --> $DIR/issue-67185-2.rs:14:5 | -LL | / trait Foo -LL | | -LL | | where -LL | | [::Quaks; 2]: Bar, -LL | | ::Quaks: Bar, -LL | | { -LL | | } - | |_^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` +LL | [::Quaks; 2]: Bar, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` | = help: the following implementations were found: <[[u16; 3]; 3] as Bar> @@ -35,7 +23,7 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -44,16 +32,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | ::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:22:6 + --> $DIR/issue-67185-2.rs:21:6 | LL | impl Foo for FooImpl {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -62,16 +50,16 @@ LL | impl Foo for FooImpl {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[[u16; 3]; 2]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[[u16; 3]; 2]` @@ -80,16 +68,16 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:15:34 + --> $DIR/issue-67185-2.rs:14:30 | LL | trait Foo | --- required by a bound in this -... -LL | [::Quaks; 2]: Bar, - | ^^^ required by this bound in `Foo` +LL | where +LL | [::Quaks; 2]: Bar, + | ^^^ required by this bound in `Foo` error[E0277]: the trait bound `[u16; 3]: Bar` is not satisfied - --> $DIR/issue-67185-2.rs:26:14 + --> $DIR/issue-67185-2.rs:25:14 | LL | fn f(_: impl Foo) {} | ^^^ the trait `Bar` is not implemented for `[u16; 3]` @@ -98,13 +86,13 @@ LL | fn f(_: impl Foo) {} <[[u16; 3]; 3] as Bar> <[u16; 4] as Bar> note: required by a bound in `Foo` - --> $DIR/issue-67185-2.rs:16:29 + --> $DIR/issue-67185-2.rs:15:25 | LL | trait Foo | --- required by a bound in this ... -LL | ::Quaks: Bar, - | ^^^ required by this bound in `Foo` +LL | ::Quaks: Bar, + | ^^^ required by this bound in `Foo` error: aborting due to 6 previous errors diff --git a/src/test/ui/cross/cross-fn-cache-hole.rs b/src/test/ui/cross/cross-fn-cache-hole.rs index 249c6474c9420..c38a5001ac86d 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.rs +++ b/src/test/ui/cross/cross-fn-cache-hole.rs @@ -12,8 +12,8 @@ trait Bar { } // We don't always check where clauses for sanity, but in this case // wfcheck does report an error here: -fn vacuous() //~ ERROR the trait bound `i32: Bar` is not satisfied - where i32: Foo +fn vacuous() + where i32: Foo //~ ERROR the trait bound `i32: Bar` is not satisfied { // ... the original intention was to check that we don't use that // vacuous where clause (which could never be satisfied) to accept diff --git a/src/test/ui/cross/cross-fn-cache-hole.stderr b/src/test/ui/cross/cross-fn-cache-hole.stderr index 0d325bb7ec102..7e15562b0816b 100644 --- a/src/test/ui/cross/cross-fn-cache-hole.stderr +++ b/src/test/ui/cross/cross-fn-cache-hole.stderr @@ -1,14 +1,8 @@ error[E0277]: the trait bound `i32: Bar` is not satisfied - --> $DIR/cross-fn-cache-hole.rs:15:1 + --> $DIR/cross-fn-cache-hole.rs:16:11 | -LL | / fn vacuous() -LL | | where i32: Foo -LL | | { -LL | | // ... the original intention was to check that we don't use that -... | -LL | | require::(); -LL | | } - | |_^ the trait `Bar` is not implemented for `i32` +LL | where i32: Foo + | ^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr index 78904b383f49a..28c49c33bf6b5 100644 --- a/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/src/test/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -1,87 +1,71 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:10:1 + --> $DIR/feature-gate-trivial_bounds.rs:10:14 | LL | enum E where i32: Foo { V } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:12:1 + --> $DIR/feature-gate-trivial_bounds.rs:12:16 | LL | struct S where i32: Foo; - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:14:1 + --> $DIR/feature-gate-trivial_bounds.rs:14:15 | LL | trait T where i32: Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:16:1 + --> $DIR/feature-gate-trivial_bounds.rs:16:15 | LL | union U where i32: Foo { f: i32 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:20:1 + --> $DIR/feature-gate-trivial_bounds.rs:20:23 | -LL | / impl Foo for () where i32: Foo { -LL | | fn test(&self) { -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | impl Foo for () where i32: Foo { + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `i32: Foo` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:28:1 + --> $DIR/feature-gate-trivial_bounds.rs:28:14 | -LL | / fn f() where i32: Foo -LL | | { -LL | | let s = S; -LL | | 3i32.test(); -LL | | Foo::test(&4i32); -LL | | generic_function(5i32); -LL | | } - | |_^ the trait `Foo` is not implemented for `i32` +LL | fn f() where i32: Foo + | ^^^^^^^^ the trait `Foo` is not implemented for `i32` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the trait bound `String: Neg` is not satisfied - --> $DIR/feature-gate-trivial_bounds.rs:36:1 + --> $DIR/feature-gate-trivial_bounds.rs:36:38 | -LL | / fn use_op(s: String) -> String where String: ::std::ops::Neg { -LL | | -s -LL | | } - | |_^ the trait `Neg` is not implemented for `String` +LL | fn use_op(s: String) -> String where String: ::std::ops::Neg { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Neg` is not implemented for `String` | = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: `i32` is not an iterator - --> $DIR/feature-gate-trivial_bounds.rs:40:1 + --> $DIR/feature-gate-trivial_bounds.rs:40:20 | -LL | / fn use_for() where i32: Iterator { -LL | | for _ in 2i32 {} -LL | | } - | |_^ `i32` is not an iterator +LL | fn use_for() where i32: Iterator { + | ^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` @@ -89,22 +73,20 @@ LL | | } = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:52:1 + --> $DIR/feature-gate-trivial_bounds.rs:52:32 | LL | struct TwoStrs(str, str) where str: Sized; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:55:1 + --> $DIR/feature-gate-trivial_bounds.rs:55:26 | -LL | / fn unsized_local() where Dst: Sized { -LL | | let x: Dst = *(Box::new(Dst { x: 1 }) as Box>); -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn unsized_local() where Dst: Sized { + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Dst<(dyn A + 'static)>` @@ -116,12 +98,10 @@ LL | struct Dst { = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/feature-gate-trivial_bounds.rs:59:1 + --> $DIR/feature-gate-trivial_bounds.rs:59:30 | -LL | / fn return_str() -> str where str: Sized { -LL | | *"Sized".to_string().into_boxed_str() -LL | | } - | |_^ doesn't have a size known at compile-time +LL | fn return_str() -> str where str: Sized { + | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` = help: see issue #48214 From 50ec47aa06e96a195707fb5ee92fcd32299ca272 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sun, 14 Nov 2021 14:01:30 +0100 Subject: [PATCH 21/29] Remove workaround for the forward progress handling in LLVM --- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 6 +----- compiler/rustc_codegen_llvm/src/context.rs | 1 - compiler/rustc_codegen_llvm/src/intrinsic.rs | 9 --------- compiler/rustc_codegen_ssa/src/mir/block.rs | 11 ----------- compiler/rustc_codegen_ssa/src/traits/intrinsic.rs | 4 ---- 5 files changed, 1 insertion(+), 30 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 64bd586662d38..f3a2382ef32d9 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -316,7 +316,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { extended_asm.add_input_operand(None, "r", result.llval); extended_asm.add_clobber("memory"); extended_asm.set_volatile_flag(true); - + // We have copied the value to `result` already. return; } @@ -363,10 +363,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { cond } - fn sideeffect(&mut self) { - // TODO(antoyo) - } - fn type_test(&mut self, _pointer: Self::Value, _typeid: Self::Value) -> Self::Value { // Unsupported. self.context.new_rvalue_from_int(self.int_type, 0) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1dba264a9614a..613a8df891ce4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -597,7 +597,6 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); - ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 924bb803b368f..a7e34b080594b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -392,15 +392,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call_intrinsic("llvm.expect.i1", &[cond, self.const_bool(expected)]) } - fn sideeffect(&mut self) { - // This kind of check would make a ton of sense in the caller, but currently the only - // caller of this function is in `rustc_codegen_ssa`, which is agnostic to whether LLVM - // codegen backend being used, and so is unable to check the LLVM version. - if unsafe { llvm::LLVMRustVersionMajor() } < 12 { - self.call_intrinsic("llvm.sideeffect", &[]); - } - } - fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value { // Test the called operand using llvm.type.test intrinsic. The LowerTypeTests link-time // optimization pass replaces calls to this intrinsic with code to test type membership. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a9471f7b77160..c8f388bfa1d5a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -980,17 +980,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - if bb == target { - // This is an unconditional branch back to this same basic block. That means we - // have something like a `loop {}` statement. LLVM versions before 12.0 - // miscompile this because they assume forward progress. For older versions - // try to handle just this specific case which comes up commonly in practice - // (e.g., in embedded code). - // - // NB: the `sideeffect` currently checks for the LLVM version used internally. - bx.sideeffect(); - } - helper.funclet_br(self, &mut bx, target); } diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 78bf22ef9f2e2..02be6cd360c72 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -20,10 +20,6 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; - /// Emits a forced side effect. - /// - /// Currently has any effect only when LLVM versions prior to 12.0 are used as the backend. - fn sideeffect(&mut self); /// Trait method used to test whether a given pointer is associated with a type identifier. fn type_test(&mut self, pointer: Self::Value, typeid: Self::Value) -> Self::Value; /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in From 77b0613f1a7d420a19fdddc731e45ee0b5d7c10a Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 15 Nov 2021 19:27:42 -0500 Subject: [PATCH 22/29] Alphabetize language features This should significantly reduce the frequency of merge conflicts. --- compiler/rustc_feature/src/accepted.rs | 446 +++++++------- compiler/rustc_feature/src/active.rs | 815 ++++++++++--------------- compiler/rustc_feature/src/removed.rs | 190 +++--- src/tools/tidy/src/features.rs | 14 +- 4 files changed, 657 insertions(+), 808 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 3cb543fe3ab98..6950fae898f21 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -34,6 +34,9 @@ declare_features! ( /// These are used to test this portion of the compiler, /// they don't actually mean anything. (accepted, test_accepted_feature, "1.0.0", None, None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: for testing purposes @@ -43,266 +46,269 @@ declare_features! ( // feature-group-start: accepted features // ------------------------------------------------------------------------- + /// Allows the sysV64 ABI to be specified on all platforms + /// instead of just the platforms on which it is the C ABI. + (accepted, abi_sysv64, "1.24.0", Some(36167), None), + /// Allows the definition of associated constants in `trait` or `impl` blocks. + (accepted, associated_consts, "1.20.0", Some(29646), None), /// Allows using associated `type`s in `trait`s. (accepted, associated_types, "1.0.0", None, None), - /// Allows using assigning a default type to type parameters in algebraic data type definitions. - (accepted, default_type_params, "1.0.0", None, None), - // FIXME: explain `globs`. - (accepted, globs, "1.0.0", None, None), - /// Allows `macro_rules!` items. - (accepted, macro_rules, "1.0.0", None, None), - /// Allows use of `&foo[a..b]` as a slicing syntax. - (accepted, slicing_syntax, "1.0.0", None, None), - /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). - (accepted, struct_variant, "1.0.0", None, None), - /// Allows indexing tuples. - (accepted, tuple_indexing, "1.0.0", None, None), - /// Allows the use of `if let` expressions. - (accepted, if_let, "1.0.0", None, None), - /// Allows the use of `while let` expressions. - (accepted, while_let, "1.0.0", None, None), - /// Allows using `#![no_std]`. - (accepted, no_std, "1.6.0", None, None), + /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. + (accepted, async_await, "1.39.0", Some(50547), None), + /// Allows all literals in attribute lists and values of key-value pairs. + (accepted, attr_literals, "1.30.0", Some(34981), None), /// Allows overloading augmented assignment operations like `a += b`. (accepted, augmented_assignments, "1.8.0", Some(28235), None), + /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. + (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), + /// Allows bindings in the subpattern of a binding pattern. + /// For example, you can write `x @ Some(y)`. + (accepted, bindings_after_at, "1.56.0", Some(65490), None), /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720), None), - /// Allows `#[deprecated]` attribute. - (accepted, deprecated, "1.9.0", Some(29935), None), - /// Allows macros to appear in the type position. - (accepted, type_macros, "1.13.0", Some(27245), None), - /// Allows use of the postfix `?` operator in expressions. - (accepted, question_mark, "1.13.0", Some(31436), None), - /// Allows `..` in tuple (struct) patterns. - (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), - /// Allows some increased flexibility in the name resolution rules, - /// especially around globs and shadowing (RFC 1560). - (accepted, item_like_imports, "1.15.0", Some(35120), None), - /// Allows using `Self` and associated types in struct expressions and patterns. - (accepted, more_struct_aliases, "1.16.0", Some(37544), None), - /// Allows elision of `'static` lifetimes in `static`s and `const`s. - (accepted, static_in_const, "1.17.0", Some(35897), None), - /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. - (accepted, field_init_shorthand, "1.17.0", Some(37340), None), - /// Allows the definition recursive static items. - (accepted, static_recursion, "1.17.0", Some(29719), None), - /// Allows `pub(restricted)` visibilities (RFC 1422). - (accepted, pub_restricted, "1.18.0", Some(32409), None), - /// Allows `#![windows_subsystem]`. - (accepted, windows_subsystem, "1.18.0", Some(37499), None), - /// Allows `break {expr}` with a value inside `loop`s. - (accepted, loop_break_value, "1.19.0", Some(37339), None), - /// Allows numeric fields in struct expressions and patterns. - (accepted, relaxed_adts, "1.19.0", Some(35626), None), + /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. + (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), + /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. + (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Allows `cfg(target_feature = "...")`. + (accepted, cfg_target_feature, "1.27.0", Some(29717), None), + /// Allows `cfg(target_vendor = "...")`. + (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), + /// Allows implementing `Clone` for closures where possible (RFC 2132). + (accepted, clone_closures, "1.26.0", Some(44490), None), /// Allows coercing non capturing closures to function pointers. (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None), - /// Allows attributes on struct literal fields. - (accepted, struct_field_attributes, "1.20.0", Some(38814), None), - /// Allows the definition of associated constants in `trait` or `impl` blocks. - (accepted, associated_consts, "1.20.0", Some(29646), None), /// Allows usage of the `compile_error!` macro. (accepted, compile_error, "1.20.0", Some(40872), None), - /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). - (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), - /// Allows `Drop` types in constants (RFC 1440). - (accepted, drop_types_in_const, "1.22.0", Some(33156), None), - /// Allows the sysV64 ABI to be specified on all platforms - /// instead of just the platforms on which it is the C ABI. - (accepted, abi_sysv64, "1.24.0", Some(36167), None), - /// Allows `repr(align(16))` struct attribute (RFC 1358). - (accepted, repr_align, "1.25.0", Some(33626), None), - /// Allows '|' at beginning of match arms (RFC 1925). - (accepted, match_beginning_vert, "1.25.0", Some(44101), None), - /// Allows nested groups in `use` items (RFC 2128). - (accepted, use_nested_groups, "1.25.0", Some(44494), None), + /// Allows `impl Trait` in function return types. + (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), + /// Allows calling constructor functions in `const fn`. + (accepted, const_constructor, "1.40.0", Some(61456), None), + /// Allows calling `transmute` in const fn + (accepted, const_fn_transmute, "1.56.0", Some(53605), None), + /// Allows accessing fields of unions inside `const` functions. + (accepted, const_fn_union, "1.56.0", Some(51909), None), + /// Allows unsizing coercions in `const fn`. + (accepted, const_fn_unsize, "1.54.0", Some(64992), None), + /// Allows the use of `if` and `match` in constants. + (accepted, const_if_match, "1.46.0", Some(49146), None), /// Allows indexing into constant arrays. (accepted, const_indexing, "1.26.0", Some(29947), None), - /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. - (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), - /// Allows `..=` in patterns (RFC 1192). - (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), - /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). - (accepted, termination_trait, "1.26.0", Some(43301), None), - /// Allows implementing `Clone` for closures where possible (RFC 2132). - (accepted, clone_closures, "1.26.0", Some(44490), None), + /// Allows let bindings, assignments and destructuring in `const` functions and constants. + /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used + /// at the same time as let bindings. + (accepted, const_let, "1.33.0", Some(48821), None), + /// Allows the use of `loop` and `while` in constants. + (accepted, const_loop, "1.46.0", Some(52000), None), + /// Allows panicking during const eval (producing compile-time errors). + (accepted, const_panic, "1.57.0", Some(51999), None), + /// Allows dereferencing raw pointers during const eval. + (accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None), /// Allows implementing `Copy` for closures where possible (RFC 2132). (accepted, copy_closures, "1.26.0", Some(44490), None), - /// Allows `impl Trait` in function arguments. - (accepted, universal_impl_trait, "1.26.0", Some(34511), None), - /// Allows `impl Trait` in function return types. - (accepted, conservative_impl_trait, "1.26.0", Some(34511), None), - /// Allows using the `u128` and `i128` types. - (accepted, i128_type, "1.26.0", Some(35118), None), - /// Allows default match binding modes (RFC 2005). - (accepted, match_default_bindings, "1.26.0", Some(42640), None), - /// Allows `'_` placeholder lifetimes. - (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), - /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). - (accepted, generic_param_attrs, "1.27.0", Some(48848), None), - /// Allows `cfg(target_feature = "...")`. - (accepted, cfg_target_feature, "1.27.0", Some(29717), None), - /// Allows `#[target_feature(...)]`. - (accepted, target_feature, "1.27.0", None, None), - /// Allows using `dyn Trait` as a syntax for trait objects. - (accepted, dyn_trait, "1.27.0", Some(44662), None), - /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). - (accepted, fn_must_use, "1.27.0", Some(43302), None), - /// Allows use of the `:lifetime` macro fragment specifier. - (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), - /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). - (accepted, termination_trait_test, "1.27.0", Some(48854), None), - /// Allows the `#[global_allocator]` attribute. - (accepted, global_allocator, "1.28.0", Some(27389), None), - /// Allows `#[repr(transparent)]` attribute on newtype structs. - (accepted, repr_transparent, "1.28.0", Some(43036), None), - /// Allows procedural macros in `proc-macro` crates. - (accepted, proc_macro, "1.29.0", Some(38356), None), - /// Allows `foo.rs` as an alternative to `foo/mod.rs`. - (accepted, non_modrs_mods, "1.30.0", Some(44660), None), - /// Allows use of the `:vis` macro fragment specifier - (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), - /// Allows importing and reexporting macros with `use`, - /// enables macro modularization in general. - (accepted, use_extern_macros, "1.30.0", Some(35896), None), - /// Allows keywords to be escaped for use as identifiers. - (accepted, raw_identifiers, "1.30.0", Some(48589), None), - /// Allows attributes scoped to tools. - (accepted, tool_attributes, "1.30.0", Some(44690), None), - /// Allows multi-segment paths in attributes and derives. - (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), - /// Allows all literals in attribute lists and values of key-value pairs. - (accepted, attr_literals, "1.30.0", Some(34981), None), - /// Allows inferring outlives requirements (RFC 2093). - (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), - /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. - /// This defines the behavior of panics. - (accepted, panic_handler, "1.30.0", Some(44489), None), - /// Allows `#[used]` to preserve symbols (see llvm.compiler.used). - (accepted, used, "1.30.0", Some(40289), None), /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477), None), + /// Allows using assigning a default type to type parameters in algebraic data type definitions. + (accepted, default_type_params, "1.0.0", None, None), + /// Allows `#[deprecated]` attribute. + (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows `#[doc(alias = "...")]`. + (accepted, doc_alias, "1.48.0", Some(50146), None), + /// Allows `..` in tuple (struct) patterns. + (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None), + /// Allows `..=` in patterns (RFC 1192). + (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + /// Allows `Drop` types in constants (RFC 1440). + (accepted, drop_types_in_const, "1.22.0", Some(33156), None), + /// Allows using `dyn Trait` as a syntax for trait objects. + (accepted, dyn_trait, "1.27.0", Some(44662), None), + /// Allows integer match exhaustiveness checking (RFC 2591). + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), + /// Allows arbitrary expressions in key-value attributes at parse time. + (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660), None), + /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. + (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), + /// Allows `extern crate self as foo;`. + /// This puts local crate root into extern prelude under name `foo`. + (accepted, extern_crate_self, "1.34.0", Some(56409), None), /// Allows access to crate names passed via `--extern` through prelude. (accepted, extern_prelude, "1.30.0", Some(44660), None), - /// Allows parentheses in patterns. - (accepted, pattern_parentheses, "1.31.0", Some(51087), None), - /// Allows the definition of `const fn` functions. - (accepted, min_const_fn, "1.31.0", Some(53555), None), - /// Allows scoped lints. - (accepted, tool_lints, "1.31.0", Some(44690), None), + /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. + (accepted, field_init_shorthand, "1.17.0", Some(37340), None), + /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940). + (accepted, fn_must_use, "1.27.0", Some(43302), None), + /// Allows capturing variables in scope using format_args! + (accepted, format_args_capture, "1.58.0", Some(67984), None), + /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327). + (accepted, generic_param_attrs, "1.27.0", Some(48848), None), + /// Allows the `#[global_allocator]` attribute. + (accepted, global_allocator, "1.28.0", Some(27389), None), + // FIXME: explain `globs`. + (accepted, globs, "1.0.0", None, None), + /// Allows using the `u128` and `i128` types. + (accepted, i128_type, "1.26.0", Some(35118), None), + /// Allows the use of `if let` expressions. + (accepted, if_let, "1.0.0", None, None), + /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. + (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), /// Allows lifetime elision in `impl` headers. For example: /// + `impl Iterator for &mut Iterator` /// + `impl Debug for Foo<'_>` (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None), - /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. - (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), - /// Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - /// Allows use of `?` as the Kleene "at most one" operator in macros. - (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), - /// Allows `Self` struct constructor (RFC 2302). - (accepted, self_struct_ctor, "1.32.0", Some(51994), None), - /// Allows `Self` in type definitions (RFC 2300). - (accepted, self_in_typedefs, "1.32.0", Some(49303), None), - /// Allows `use x::y;` to search `x` in the current scope. - (accepted, uniform_paths, "1.32.0", Some(53130), None), - /// Allows integer match exhaustiveness checking (RFC 2591). - (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), - /// Allows `use path as _;` and `extern crate c as _;`. - (accepted, underscore_imports, "1.33.0", Some(48216), None), - /// Allows `#[repr(packed(N))]` attribute on structs. - (accepted, repr_packed, "1.33.0", Some(33158), None), + /// Allows using `a..=b` and `..=b` as inclusive range syntaxes. + (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), + /// Allows inferring outlives requirements (RFC 2093). + (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None), /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086). (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None), - /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. - (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), - /// Allows let bindings, assignments and destructuring in `const` functions and constants. - /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used - /// at the same time as let bindings. - (accepted, const_let, "1.33.0", Some(48821), None), - /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. - (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), - /// Allows top level or-patterns (`p | q`) in `if let` and `while let`. - (accepted, if_while_or_patterns, "1.33.0", Some(48215), None), - /// Allows `cfg(target_vendor = "...")`. - (accepted, cfg_target_vendor, "1.33.0", Some(29718), None), - /// Allows `extern crate self as foo;`. - /// This puts local crate root into extern prelude under name `foo`. - (accepted, extern_crate_self, "1.34.0", Some(56409), None), - /// Allows arbitrary delimited token streams in non-macro attributes. - (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), - /// Allows paths to enum variants on type aliases including `Self`. - (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), - /// Allows using `#[repr(align(X))]` on enums with equivalent semantics - /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. - (accepted, repr_align_enum, "1.37.0", Some(57996), None), - /// Allows `const _: TYPE = VALUE`. - (accepted, underscore_const_names, "1.37.0", Some(54912), None), - /// Allows free and inherent `async fn`s, `async` blocks, and `.await` expressions. - (accepted, async_await, "1.39.0", Some(50547), None), - /// Allows mixing bind-by-move in patterns and references to those identifiers in guards. - (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None), - /// Allows attributes in formal function parameters. - (accepted, param_attrs, "1.39.0", Some(60406), None), + /// Allows some increased flexibility in the name resolution rules, + /// especially around globs and shadowing (RFC 1560). + (accepted, item_like_imports, "1.15.0", Some(35120), None), + /// Allows `break {expr}` with a value inside `loop`s. + (accepted, loop_break_value, "1.19.0", Some(37339), None), + /// Allows use of `?` as the Kleene "at most one" operator in macros. + (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), + /// Allows macro attributes to observe output of `#[derive]`. + (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None), + /// Allows use of the `:lifetime` macro fragment specifier. + (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None), + /// Allows use of the `:literal` macro fragment specifier (RFC 1576). + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), + /// Allows `macro_rules!` items. + (accepted, macro_rules, "1.0.0", None, None), + /// Allows use of the `:vis` macro fragment specifier + (accepted, macro_vis_matcher, "1.30.0", Some(41022), None), /// Allows macro invocations in `extern {}` blocks. (accepted, macros_in_extern, "1.40.0", Some(49476), None), + /// Allows '|' at beginning of match arms (RFC 1925). + (accepted, match_beginning_vert, "1.25.0", Some(44101), None), + /// Allows default match binding modes (RFC 2005). + (accepted, match_default_bindings, "1.26.0", Some(42640), None), + /// Allows `impl Trait` with multiple unrelated lifetimes. + (accepted, member_constraints, "1.54.0", Some(61997), None), + /// Allows the definition of `const fn` functions. + (accepted, min_const_fn, "1.31.0", Some(53555), None), + /// The smallest useful subset of const generics. + (accepted, min_const_generics, "1.51.0", Some(74878), None), + /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions. + (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None), + /// Allows using `Self` and associated types in struct expressions and patterns. + (accepted, more_struct_aliases, "1.16.0", Some(37544), None), + /// Allows patterns with concurrent by-move and by-ref bindings. + /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. + (accepted, move_ref_pattern, "1.49.0", Some(68354), None), + /// Allows using `#![no_std]`. + (accepted, no_std, "1.6.0", None, None), + /// Allows defining identifiers beyond ASCII. + (accepted, non_ascii_idents, "1.53.0", Some(55467), None), /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008). (accepted, non_exhaustive, "1.40.0", Some(44109), None), - /// Allows calling constructor functions in `const fn`. - (accepted, const_constructor, "1.40.0", Some(61456), None), - /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. - (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Allows `foo.rs` as an alternative to `foo/mod.rs`. + (accepted, non_modrs_mods, "1.30.0", Some(44660), None), + /// Allows the use of or-patterns (e.g., `0 | 1`). + (accepted, or_patterns, "1.53.0", Some(54883), None), + /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`. + /// This defines the behavior of panics. + (accepted, panic_handler, "1.30.0", Some(44489), None), + /// Allows attributes in formal function parameters. + (accepted, param_attrs, "1.39.0", Some(60406), None), + /// Allows parentheses in patterns. + (accepted, pattern_parentheses, "1.31.0", Some(51087), None), + /// Allows procedural macros in `proc-macro` crates. + (accepted, proc_macro, "1.29.0", Some(38356), None), + /// Allows multi-segment paths in attributes and derives. + (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None), + /// Allows `pub(restricted)` visibilities (RFC 1422). + (accepted, pub_restricted, "1.18.0", Some(32409), None), + /// Allows use of the postfix `?` operator in expressions. + (accepted, question_mark, "1.13.0", Some(31436), None), + /// Allows keywords to be escaped for use as identifiers. + (accepted, raw_identifiers, "1.30.0", Some(48589), None), /// Allows relaxing the coherence rules such that /// `impl ForeignTrait for ForeignType` is permitted. (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None), - /// Allows #[repr(transparent)] on univariant enums (RFC 2645). - (accepted, transparent_enums, "1.42.0", Some(60405), None), + /// Allows numeric fields in struct expressions and patterns. + (accepted, relaxed_adts, "1.19.0", Some(35626), None), + /// Lessens the requirements for structs to implement `Unsize`. + (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None), + /// Allows `repr(align(16))` struct attribute (RFC 1358). + (accepted, repr_align, "1.25.0", Some(33626), None), + /// Allows using `#[repr(align(X))]` on enums with equivalent semantics + /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`. + (accepted, repr_align_enum, "1.37.0", Some(57996), None), + /// Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), + /// Allows `#[repr(transparent)]` attribute on newtype structs. + (accepted, repr_transparent, "1.28.0", Some(43036), None), + /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). + (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None), + /// Allows `Self` in type definitions (RFC 2300). + (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + /// Allows `Self` struct constructor (RFC 2302). + (accepted, self_struct_ctor, "1.32.0", Some(51994), None), /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. (accepted, slice_patterns, "1.42.0", Some(62254), None), - /// Allows the use of `if` and `match` in constants. - (accepted, const_if_match, "1.46.0", Some(49146), None), - /// Allows the use of `loop` and `while` in constants. - (accepted, const_loop, "1.46.0", Some(52000), None), + /// Allows use of `&foo[a..b]` as a slicing syntax. + (accepted, slicing_syntax, "1.0.0", None, None), + /// Allows elision of `'static` lifetimes in `static`s and `const`s. + (accepted, static_in_const, "1.17.0", Some(35897), None), + /// Allows the definition recursive static items. + (accepted, static_recursion, "1.17.0", Some(29719), None), + /// Allows attributes on struct literal fields. + (accepted, struct_field_attributes, "1.20.0", Some(38814), None), + /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418). + (accepted, struct_variant, "1.0.0", None, None), + /// Allows `#[target_feature(...)]`. + (accepted, target_feature, "1.27.0", None, None), + /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). + (accepted, termination_trait, "1.26.0", Some(43301), None), + /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). + (accepted, termination_trait_test, "1.27.0", Some(48854), None), + /// Allows attributes scoped to tools. + (accepted, tool_attributes, "1.30.0", Some(44690), None), + /// Allows scoped lints. + (accepted, tool_lints, "1.31.0", Some(44690), None), /// Allows `#[track_caller]` to be used which provides /// accurate caller location reporting during panic (RFC 2091). (accepted, track_caller, "1.46.0", Some(47809), None), - /// Allows `#[doc(alias = "...")]`. - (accepted, doc_alias, "1.48.0", Some(50146), None), - /// Allows patterns with concurrent by-move and by-ref bindings. - /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. - (accepted, move_ref_pattern, "1.49.0", Some(68354), None), - /// The smallest useful subset of const generics. - (accepted, min_const_generics, "1.51.0", Some(74878), None), + /// Allows #[repr(transparent)] on univariant enums (RFC 2645). + (accepted, transparent_enums, "1.42.0", Some(60405), None), + /// Allows indexing tuples. + (accepted, tuple_indexing, "1.0.0", None, None), + /// Allows paths to enum variants on type aliases including `Self`. + (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None), + /// Allows macros to appear in the type position. + (accepted, type_macros, "1.13.0", Some(27245), None), + /// Allows `const _: TYPE = VALUE`. + (accepted, underscore_const_names, "1.37.0", Some(54912), None), + /// Allows `use path as _;` and `extern crate c as _;`. + (accepted, underscore_imports, "1.33.0", Some(48216), None), + /// Allows `'_` placeholder lifetimes. + (accepted, underscore_lifetimes, "1.26.0", Some(44524), None), + /// Allows `use x::y;` to search `x` in the current scope. + (accepted, uniform_paths, "1.32.0", Some(53130), None), + /// Allows `impl Trait` in function arguments. + (accepted, universal_impl_trait, "1.26.0", Some(34511), None), + /// Allows arbitrary delimited token streams in non-macro attributes. + (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None), /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block. (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None), - /// Allows the use of or-patterns (e.g., `0 | 1`). - (accepted, or_patterns, "1.53.0", Some(54883), None), - /// Allows defining identifiers beyond ASCII. - (accepted, non_ascii_idents, "1.53.0", Some(55467), None), - /// Allows arbitrary expressions in key-value attributes at parse time. - (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None), - /// Allows unsizing coercions in `const fn`. - (accepted, const_fn_unsize, "1.54.0", Some(64992), None), - /// Allows `impl Trait` with multiple unrelated lifetimes. - (accepted, member_constraints, "1.54.0", Some(61997), None), - /// Allows bindings in the subpattern of a binding pattern. - /// For example, you can write `x @ Some(y)`. - (accepted, bindings_after_at, "1.56.0", Some(65490), None), - /// Allows calling `transmute` in const fn - (accepted, const_fn_transmute, "1.56.0", Some(53605), None), - /// Allows accessing fields of unions inside `const` functions. - (accepted, const_fn_union, "1.56.0", Some(51909), None), - /// Allows macro attributes to observe output of `#[derive]`. - (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None), - /// Allows panicking during const eval (producing compile-time errors). - (accepted, const_panic, "1.57.0", Some(51999), None), - /// Lessens the requirements for structs to implement `Unsize`. - (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None), - /// Allows dereferencing raw pointers during const eval. - (accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None), - /// Allows capturing variables in scope using format_args! - (accepted, format_args_capture, "1.58.0", Some(67984), None), + /// Allows importing and reexporting macros with `use`, + /// enables macro modularization in general. + (accepted, use_extern_macros, "1.30.0", Some(35896), None), + /// Allows nested groups in `use` items (RFC 2128). + (accepted, use_nested_groups, "1.25.0", Some(44494), None), + /// Allows `#[used]` to preserve symbols (see llvm.compiler.used). + (accepted, used, "1.30.0", Some(40289), None), + /// Allows the use of `while let` expressions. + (accepted, while_let, "1.0.0", None, None), + /// Allows `#![windows_subsystem]`. + (accepted, windows_subsystem, "1.18.0", Some(37499), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 61dd505e1e912..608581306bef5 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -122,130 +122,101 @@ impl Feature { #[rustfmt::skip] declare_features! ( // ------------------------------------------------------------------------- - // feature-group-start: internal feature gates + // feature-group-start: internal feature gates (no tracking issue) // ------------------------------------------------------------------------- - // no-tracking-issue-start - /// Allows using `rustc_*` attributes (RFC 572). - (active, rustc_attrs, "1.0.0", None, None), - - /// Allows using compiler's own crates. - (active, rustc_private, "1.0.0", Some(27812), None), - - /// Allows using the `rust-intrinsic`'s "ABI". - (active, intrinsics, "1.0.0", None, None), - - /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. - (active, lang_items, "1.0.0", None, None), - - /// Allows using the `#[stable]` and `#[unstable]` attributes. - (active, staged_api, "1.0.0", None, None), - - /// Allows using `#[allow_internal_unstable]`. This is an + /// Allows using the `thiscall` ABI. + (active, abi_thiscall, "1.19.0", None, None), + /// Allows using the `unadjusted` ABI; perma-unstable. + (active, abi_unadjusted, "1.16.0", None, None), + /// Allows using the `vectorcall` ABI. + (active, abi_vectorcall, "1.7.0", None, None), + /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. + (active, allocator_internals, "1.20.0", None, None), + /// Allows using `#[allow_internal_unsafe]`. This is an /// attribute on `macro_rules!` and can't use the attribute handling /// below (it has to be checked before expansion possibly makes /// macros disappear). - (active, allow_internal_unstable, "1.0.0", None, None), - - /// Allows using `#[allow_internal_unsafe]`. This is an + (active, allow_internal_unsafe, "1.0.0", None, None), + /// Allows using `#[allow_internal_unstable]`. This is an /// attribute on `macro_rules!` and can't use the attribute handling /// below (it has to be checked before expansion possibly makes /// macros disappear). - (active, allow_internal_unsafe, "1.0.0", None, None), - - /// no-tracking-issue-end - - /// Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), - - /// Allows using the `box $expr` syntax. - (active, box_syntax, "1.0.0", Some(49733), None), - - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. - (active, start, "1.0.0", Some(29633), None), - - /// Allows using the `#[fundamental]` attribute. - (active, fundamental, "1.0.0", Some(29635), None), - - /// Allows using the `rust-call` ABI. - (active, unboxed_closures, "1.0.0", Some(29625), None), - - /// Allows using the `#[linkage = ".."]` attribute. - (active, linkage, "1.0.0", Some(29603), None), - - /// Allows using `box` in patterns (RFC 469). - (active, box_patterns, "1.0.0", Some(29641), None), - - // no-tracking-issue-start - - /// Allows using `#[prelude_import]` on glob `use` items. - (active, prelude_import, "1.2.0", None, None), - - // no-tracking-issue-end - - // no-tracking-issue-start - - /// Allows using `#[omit_gdb_pretty_printer_section]`. - (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), - - /// Allows using the `vectorcall` ABI. - (active, abi_vectorcall, "1.7.0", None, None), - - // no-tracking-issue-end - - /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. - /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library - /// feature with the same name exists. - (active, structural_match, "1.8.0", Some(31434), None), - - /// Allows using the `may_dangle` attribute (RFC 1327). - (active, dropck_eyepatch, "1.10.0", Some(34761), None), - - /// Allows using the `#![panic_runtime]` attribute. - (active, panic_runtime, "1.10.0", Some(32837), None), - - /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. - (active, needs_panic_runtime, "1.10.0", Some(32837), None), - - // no-tracking-issue-start - + (active, allow_internal_unstable, "1.0.0", None, None), /// Allows identifying the `compiler_builtins` crate. (active, compiler_builtins, "1.13.0", None, None), - - /// Allows using the `unadjusted` ABI; perma-unstable. - (active, abi_unadjusted, "1.16.0", None, None), - + /// Allows using the `rust-intrinsic`'s "ABI". + (active, intrinsics, "1.0.0", None, None), + /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic. + (active, lang_items, "1.0.0", None, None), + /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`, + /// it is not on path for eventual stabilization). + (active, no_niche, "1.42.0", None, None), + /// Allows using `#[omit_gdb_pretty_printer_section]`. + (active, omit_gdb_pretty_printer_section, "1.5.0", None, None), + /// Allows using `#[prelude_import]` on glob `use` items. + (active, prelude_import, "1.2.0", None, None), /// Used to identify crates that contain the profiler runtime. (active, profiler_runtime, "1.18.0", None, None), - - /// Allows using the `thiscall` ABI. - (active, abi_thiscall, "1.19.0", None, None), - - /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`. - (active, allocator_internals, "1.20.0", None, None), - + /// Allows using `rustc_*` attributes (RFC 572). + (active, rustc_attrs, "1.0.0", None, None), + /// Allows using the `#[stable]` and `#[unstable]` attributes. + (active, staged_api, "1.0.0", None, None), /// Added for testing E0705; perma-unstable. (active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! - /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`, - /// it is not on path for eventual stabilization). - (active, no_niche, "1.42.0", None, None), + // no-tracking-issue-end + // ------------------------------------------------------------------------- + // feature-group-end: internal feature gates (no tracking issue) + // ------------------------------------------------------------------------- - /// Allows using `#[rustc_allow_const_fn_unstable]`. - /// This is an attribute on `const fn` for the same - /// purpose as `#[allow_internal_unstable]`. - (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None), + // ------------------------------------------------------------------------- + // feature-group-start: internal feature gates + // ------------------------------------------------------------------------- /// Allows features specific to auto traits. /// Renamed from `optin_builtin_traits`. (active, auto_traits, "1.50.0", Some(13231), None), - + /// Allows using `box` in patterns (RFC 469). + (active, box_patterns, "1.0.0", Some(29641), None), + /// Allows using the `box $expr` syntax. + (active, box_syntax, "1.0.0", Some(49733), None), /// Allows `#[doc(notable_trait)]`. /// Renamed from `doc_spotlight`. (active, doc_notable_trait, "1.52.0", Some(45040), None), - - // no-tracking-issue-end + /// Allows using the `may_dangle` attribute (RFC 1327). + (active, dropck_eyepatch, "1.10.0", Some(34761), None), + /// Allows using the `#[fundamental]` attribute. + (active, fundamental, "1.0.0", Some(29635), None), + /// Allows using `#[link_name="llvm.*"]`. + (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + /// Allows using the `#[linkage = ".."]` attribute. + (active, linkage, "1.0.0", Some(29603), None), + /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. + (active, needs_panic_runtime, "1.10.0", Some(32837), None), + /// Allows using the `#![panic_runtime]` attribute. + (active, panic_runtime, "1.10.0", Some(32837), None), + /// Allows using `#[rustc_allow_const_fn_unstable]`. + /// This is an attribute on `const fn` for the same + /// purpose as `#[allow_internal_unstable]`. + (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None), + /// Allows using compiler's own crates. + (active, rustc_private, "1.0.0", Some(27812), None), + /// Allows using `#[start]` on a function indicating that it is the program entrypoint. + (active, start, "1.0.0", Some(29633), None), + /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. + /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library + /// feature with the same name exists. + (active, structural_match, "1.8.0", Some(31434), None), + /// Allows using the `rust-call` ABI. + (active, unboxed_closures, "1.0.0", Some(29625), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: internal feature gates @@ -258,23 +229,26 @@ declare_features! ( // FIXME: Document these and merge with the list below. // Unstable `#[target_feature]` directives. - (active, arm_target_feature, "1.27.0", Some(44839), None), (active, aarch64_target_feature, "1.27.0", Some(44839), None), + (active, adx_target_feature, "1.32.0", Some(44839), None), + (active, arm_target_feature, "1.27.0", Some(44839), None), + (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, bpf_target_feature, "1.54.0", Some(44839), None), + (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), + (active, ermsb_target_feature, "1.49.0", Some(44839), None), + (active, f16c_target_feature, "1.36.0", Some(44839), None), (active, hexagon_target_feature, "1.27.0", Some(44839), None), - (active, powerpc_target_feature, "1.27.0", Some(44839), None), (active, mips_target_feature, "1.27.0", Some(44839), None), - (active, avx512_target_feature, "1.27.0", Some(44839), None), + (active, movbe_target_feature, "1.34.0", Some(44839), None), + (active, powerpc_target_feature, "1.27.0", Some(44839), None), + (active, riscv_target_feature, "1.45.0", Some(44839), None), + (active, rtm_target_feature, "1.35.0", Some(44839), None), (active, sse4a_target_feature, "1.27.0", Some(44839), None), (active, tbm_target_feature, "1.27.0", Some(44839), None), (active, wasm_target_feature, "1.30.0", Some(44839), None), - (active, adx_target_feature, "1.32.0", Some(44839), None), - (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None), - (active, movbe_target_feature, "1.34.0", Some(44839), None), - (active, rtm_target_feature, "1.35.0", Some(44839), None), - (active, f16c_target_feature, "1.36.0", Some(44839), None), - (active, riscv_target_feature, "1.45.0", Some(44839), None), - (active, ermsb_target_feature, "1.49.0", Some(44839), None), - (active, bpf_target_feature, "1.54.0", Some(44839), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: actual feature gates (target features) @@ -284,416 +258,287 @@ declare_features! ( // feature-group-start: actual feature gates // ------------------------------------------------------------------------- - /// Allows using `#![plugin(myplugin)]`. - (active, plugin, "1.0.0", Some(29597), None), - - /// Allows using `#[thread_local]` on `static` items. - (active, thread_local, "1.0.0", Some(29594), None), - - /// Allows the use of SIMD types in functions declared in `extern` blocks. - (active, simd_ffi, "1.0.0", Some(27731), None), - - /// Allows using non lexical lifetimes (RFC 2094). - (active, nll, "1.0.0", Some(43234), None), - + /// Allows using the `amdgpu-kernel` ABI. + (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), + /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. + (active, abi_avr_interrupt, "1.45.0", Some(69664), None), + /// Allows `extern "C-cmse-nonsecure-call" fn()`. + (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None), + /// Allows using the `efiapi` ABI. + (active, abi_efiapi, "1.40.0", Some(65815), None), + /// Allows `extern "msp430-interrupt" fn()`. + (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), + /// Allows `extern "ptx-*" fn()`. + (active, abi_ptx, "1.15.0", Some(38788), None), + /// Allows `extern "x86-interrupt" fn()`. + (active, abi_x86_interrupt, "1.17.0", Some(40180), None), + /// Allows additional const parameter types, such as `&'static str` or user defined types + (incomplete, adt_const_params, "1.56.0", Some(44580), None), + /// Allows defining an `#[alloc_error_handler]`. + (active, alloc_error_handler, "1.29.0", Some(51540), None), + /// Allows a test to fail without failing the whole suite. + (active, allow_fail, "1.19.0", Some(46488), None), + /// Allows explicit discriminants on non-unit enum variants. + (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), + /// Allows trait methods with arbitrary self types. + (active, arbitrary_self_types, "1.23.0", Some(44874), None), + /// Allows using `const` operands in inline assembly. + (active, asm_const, "1.58.0", Some(72016), None), + /// Enables experimental inline assembly support for additional architectures. + (active, asm_experimental_arch, "1.58.0", Some(72016), None), + /// Allows using `sym` operands in inline assembly. + (active, asm_sym, "1.58.0", Some(72016), None), + /// Allows the user of associated type bounds. + (active, associated_type_bounds, "1.34.0", Some(52662), None), /// Allows associated type defaults. (active, associated_type_defaults, "1.2.0", Some(29661), None), - - /// Allows `#![no_core]`. - (active, no_core, "1.3.0", Some(29639), None), - - /// Allows default type parameters to influence type inference. - (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), - - /// Allows `repr(simd)` and importing the various simd intrinsics. - (active, repr_simd, "1.4.0", Some(27731), None), - - /// Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), - - /// Allows attributes on expressions and non-item statements. - (active, stmt_expr_attributes, "1.6.0", Some(15701), None), - - /// Allows the use of type ascription in expressions. - (active, type_ascription, "1.6.0", Some(23416), None), - - /// Allows `cfg(target_thread_local)`. - (active, cfg_target_thread_local, "1.7.0", Some(29594), None), - - /// Allows specialization of implementations (RFC 1210). - (incomplete, specialization, "1.7.0", Some(31844), None), - - /// A minimal, sound subset of specialization intended to be used by the - /// standard library until the soundness issues with specialization - /// are fixed. - (active, min_specialization, "1.7.0", Some(31844), None), - - /// Allows using `#[naked]` on functions. - (active, naked_functions, "1.9.0", Some(32408), None), - + /// Allows `async || body` closures. + (active, async_closure, "1.37.0", Some(62290), None), + /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. + (active, c_unwind, "1.52.0", Some(74990), None), + /// Allows using C-variadics. + (active, c_variadic, "1.34.0", Some(44930), None), + /// Allows capturing disjoint fields in a closure/generator (RFC 2229). + (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), + /// Enables `#[cfg(panic = "...")]` config key. + (active, cfg_panic, "1.49.0", Some(77443), None), + /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. + (active, cfg_sanitize, "1.41.0", Some(39699), None), + /// Allows `cfg(target_abi = "...")`. + (active, cfg_target_abi, "1.55.0", Some(80970), None), /// Allows `cfg(target_has_atomic = "...")`. (active, cfg_target_has_atomic, "1.9.0", Some(32976), None), - - /// Allows `X..Y` patterns. - (active, exclusive_range_pattern, "1.11.0", Some(37854), None), - - /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. - (active, never_type, "1.13.0", Some(35121), None), - - /// Allows exhaustive pattern matching on types that contain uninhabited types. - (active, exhaustive_patterns, "1.13.0", Some(51085), None), - - /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields - /// that don't implement `Copy` as long as they don't have any drop glue. - /// This is checked recursively. On encountering type variable where no progress can be made, - /// `T: Copy` is used as a substitute for "no drop glue". - /// - /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. - (active, untagged_unions, "1.13.0", Some(55149), None), - - /// Allows `#[link(..., cfg(..))]`. - (active, link_cfg, "1.14.0", Some(37406), None), - - /// Allows `extern "ptx-*" fn()`. - (active, abi_ptx, "1.15.0", Some(38788), None), - - /// Allows the `#[repr(i128)]` attribute for enums. - (incomplete, repr128, "1.16.0", Some(56071), None), - - /// Allows `#[link(kind="static-nobundle"...)]`. - (active, static_nobundle, "1.16.0", Some(37403), None), - - /// Allows `extern "msp430-interrupt" fn()`. - (active, abi_msp430_interrupt, "1.16.0", Some(38487), None), - + /// Allows `cfg(target_thread_local)`. + (active, cfg_target_thread_local, "1.7.0", Some(29594), None), + /// Allow conditional compilation depending on rust version + (active, cfg_version, "1.45.0", Some(64796), None), + /// Allows `#[track_caller]` on closures and generators. + (active, closure_track_caller, "1.57.0", Some(87417), None), + /// Allows to use the `#[cmse_nonsecure_entry]` attribute. + (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), + /// Allows `async {}` expressions in const contexts. + (active, const_async_blocks, "1.53.0", Some(85368), None), + // Allows limiting the evaluation steps of const expressions + (active, const_eval_limit, "1.43.0", Some(67217), None), + /// Allows the definition of `const extern fn` and `const unsafe extern fn`. + (active, const_extern_fn, "1.40.0", Some(64926), None), + /// Allows basic arithmetic on floating point types in a `const fn`. + (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), + /// Allows using and casting function pointers in a `const fn`. + (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), + /// Allows trait bounds in `const fn`. + (active, const_fn_trait_bound, "1.53.0", Some(57563), None), + /// Allows `for _ in _` loops in const contexts. + (active, const_for, "1.56.0", Some(87575), None), + /// Allows const generics to have default values (e.g. `struct Foo(...);`). + (active, const_generics_defaults, "1.51.0", Some(44580), None), + /// Allows argument and return position `impl Trait` in a `const fn`. + (active, const_impl_trait, "1.48.0", Some(77463), None), + /// Allows using `&mut` in constant functions. + (active, const_mut_refs, "1.41.0", Some(57349), None), + /// Be more precise when looking for live drops in a const context. + (active, const_precise_live_drops, "1.46.0", Some(73255), None), + /// Allows references to types with interior mutability within constants + (active, const_refs_to_cell, "1.51.0", Some(80384), None), + /// Allows `impl const Trait for T` syntax. + (active, const_trait_impl, "1.42.0", Some(67792), None), + /// Allows the `?` operator in const contexts. + (active, const_try, "1.56.0", Some(74935), None), + /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. + (active, crate_visibility_modifier, "1.23.0", Some(53120), None), + /// Allows non-builtin attributes in inner attribute position. + (active, custom_inner_attributes, "1.30.0", Some(54726), None), + /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. + (active, custom_test_frameworks, "1.30.0", Some(50297), None), /// Allows declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), - - /// Allows `extern "x86-interrupt" fn()`. - (active, abi_x86_interrupt, "1.17.0", Some(40180), None), - - /// Allows a test to fail without failing the whole suite. - (active, allow_fail, "1.19.0", Some(46488), None), - - /// Allows unsized tuple coercion. - (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), - - /// Allows defining generators. - (active, generators, "1.21.0", Some(43122), None), - + /// Allows rustc to inject a default alloc_error_handler + (active, default_alloc_error_handler, "1.48.0", Some(66741), None), + /// Allows default type parameters to influence type inference. + (active, default_type_parameter_fallback, "1.3.0", Some(27336), None), + /// Allows `#[derive(Default)]` and `#[default]` on enums. + (active, derive_default_enum, "1.56.0", Some(86985), None), + /// Allows the use of destructuring assignments. + (active, destructuring_assignment, "1.49.0", Some(71126), None), + /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. + (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. (active, doc_cfg, "1.21.0", Some(43781), None), - + /// Allows `#[doc(cfg_hide(...))]`. + (active, doc_cfg_hide, "1.57.0", Some(43781), None), + /// Allows using `#[doc(keyword = "...")]`. + (active, doc_keyword, "1.28.0", Some(51315), None), /// Allows `#[doc(masked)]`. (active, doc_masked, "1.21.0", Some(44027), None), - - /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`. - (active, crate_visibility_modifier, "1.23.0", Some(53120), None), - + /// Allows using doc(primitive) without a future-incompat warning + (active, doc_primitive, "1.56.0", Some(88070), None), + /// Allows `X..Y` patterns. + (active, exclusive_range_pattern, "1.11.0", Some(37854), None), + /// Allows exhaustive pattern matching on types that contain uninhabited types. + (active, exhaustive_patterns, "1.13.0", Some(51085), None), + /// Allows explicit generic arguments specification with `impl Trait` present. + (active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None), /// Allows defining `extern type`s. (active, extern_types, "1.23.0", Some(43467), None), - - /// Allows trait methods with arbitrary self types. - (active, arbitrary_self_types, "1.23.0", Some(44874), None), - - /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). - (active, in_band_lifetimes, "1.23.0", Some(44524), None), - - /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). - (active, generic_associated_types, "1.23.0", Some(44265), None), - - /// Allows defining `trait X = A + B;` alias items. - (active, trait_alias, "1.24.0", Some(41517), None), - - /// Allows inferring `'static` outlives requirements (RFC 2093). - (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), - - /// Allows inconsistent bounds in where clauses. - (active, trivial_bounds, "1.28.0", Some(48214), None), - - /// Allows `'a: { break 'a; }`. - (active, label_break_value, "1.28.0", Some(48594), None), - - /// Allows using `#[doc(keyword = "...")]`. - (active, doc_keyword, "1.28.0", Some(51315), None), - - /// Allows using `try {...}` expressions. - (active, try_blocks, "1.29.0", Some(31436), None), - - /// Allows defining an `#[alloc_error_handler]`. - (active, alloc_error_handler, "1.29.0", Some(51540), None), - - /// Allows using the `amdgpu-kernel` ABI. - (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None), - - /// Allows `#[marker]` on certain traits allowing overlapping implementations. - (active, marker_trait_attr, "1.30.0", Some(29864), None), - - /// Allows macro attributes on expressions, statements and non-inline modules. - (active, proc_macro_hygiene, "1.30.0", Some(54727), None), - - /// Allows unsized rvalues at arguments and parameters. - (incomplete, unsized_locals, "1.30.0", Some(48055), None), - - /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. - (active, custom_test_frameworks, "1.30.0", Some(50297), None), - - /// Allows non-builtin attributes in inner attribute position. - (active, custom_inner_attributes, "1.30.0", Some(54726), None), - - /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. - (active, lint_reasons, "1.31.0", Some(54503), None), - - /// Allows exhaustive integer pattern matching on `usize` and `isize`. - (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), - - /// Allows using `#[ffi_returns_twice]` on foreign functions. - (active, ffi_returns_twice, "1.34.0", Some(58314), None), - - /// Allows using `#[optimize(X)]`. - (active, optimize_attribute, "1.34.0", Some(54882), None), - - /// Allows using C-variadics. - (active, c_variadic, "1.34.0", Some(44930), None), - - /// Allows the user of associated type bounds. - (active, associated_type_bounds, "1.34.0", Some(52662), None), - - /// Allows `if/while p && let q = r && ...` chains. - (incomplete, let_chains, "1.37.0", Some(53667), None), - - /// Allows #[repr(transparent)] on unions (RFC 2645). - (active, transparent_unions, "1.37.0", Some(60405), None), - - /// Allows explicit discriminants on non-unit enum variants. - (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None), - - /// Allows `async || body` closures. - (active, async_closure, "1.37.0", Some(62290), None), - - /// Allows `impl Trait` to be used inside type aliases (RFC 2515). - (active, type_alias_impl_trait, "1.38.0", Some(63063), None), - - /// Allows the definition of `const extern fn` and `const unsafe extern fn`. - (active, const_extern_fn, "1.40.0", Some(64926), None), - - /// Allows the use of raw-dylibs (RFC 2627). - (incomplete, raw_dylib, "1.40.0", Some(58713), None), - - /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. - /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and - /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. - (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), - - /// Allows using the `efiapi` ABI. - (active, abi_efiapi, "1.40.0", Some(65815), None), - - /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. - (active, raw_ref_op, "1.41.0", Some(64490), None), - - /// Allows diverging expressions to fall back to `!` rather than `()`. - (active, never_type_fallback, "1.41.0", Some(65992), None), - - /// Allows using the `#[register_attr]` attribute. - (active, register_attr, "1.41.0", Some(66080), None), - - /// Allows using the `#[register_tool]` attribute. - (active, register_tool, "1.41.0", Some(66079), None), - - /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. - (active, cfg_sanitize, "1.41.0", Some(39699), None), - - /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. - (active, half_open_range_patterns, "1.41.0", Some(67264), None), - - /// Allows using `&mut` in constant functions. - (active, const_mut_refs, "1.41.0", Some(57349), None), - - /// Allows `impl const Trait for T` syntax. - (active, const_trait_impl, "1.42.0", Some(67792), None), - - /// Allows the use of `no_sanitize` attribute. - (active, no_sanitize, "1.42.0", Some(39699), None), - - // Allows limiting the evaluation steps of const expressions - (active, const_eval_limit, "1.43.0", Some(67217), None), - - /// Allow negative trait implementations. - (active, negative_impls, "1.44.0", Some(68318), None), - - /// Allows the use of `#[target_feature]` on safe functions. - (active, target_feature_11, "1.45.0", Some(69098), None), - - /// Allow conditional compilation depending on rust version - (active, cfg_version, "1.45.0", Some(64796), None), - - /// Allows the use of `#[ffi_pure]` on foreign functions. - (active, ffi_pure, "1.45.0", Some(58329), None), - /// Allows the use of `#[ffi_const]` on foreign functions. (active, ffi_const, "1.45.0", Some(58328), None), - - /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`. - (active, abi_avr_interrupt, "1.45.0", Some(69664), None), - - /// Be more precise when looking for live drops in a const context. - (active, const_precise_live_drops, "1.46.0", Some(73255), None), - + /// Allows the use of `#[ffi_pure]` on foreign functions. + (active, ffi_pure, "1.45.0", Some(58329), None), + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (active, ffi_returns_twice, "1.34.0", Some(58314), None), + /// Allows using `#[repr(align(...))]` on function items + (active, fn_align, "1.53.0", Some(82232), None), + /// Allows defining generators. + (active, generators, "1.21.0", Some(43122), None), + /// Infer generic args for both consts and types. + (active, generic_arg_infer, "1.55.0", Some(85077), None), + /// Allows associated types to be generic, e.g., `type Foo;` (RFC 1598). + (active, generic_associated_types, "1.23.0", Some(44265), None), + /// Allows non-trivial generic constants which have to have wfness manually propagated to callers + (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), + /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern. + (active, half_open_range_patterns, "1.41.0", Some(67264), None), /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), - - /// Allows basic arithmetic on floating point types in a `const fn`. - (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), - - /// Allows using and casting function pointers in a `const fn`. - (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), - - /// Allows to use the `#[cmse_nonsecure_entry]` attribute. - (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None), - - /// Allows rustc to inject a default alloc_error_handler - (active, default_alloc_error_handler, "1.48.0", Some(66741), None), - - /// Allows argument and return position `impl Trait` in a `const fn`. - (active, const_impl_trait, "1.48.0", Some(77463), None), - - /// Allows `#[instruction_set(_)]` attribute - (active, isa_attribute, "1.48.0", Some(74727), None), - + /// Allows using imported `main` function + (active, imported_main, "1.53.0", Some(28937), None), + /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). + (active, in_band_lifetimes, "1.23.0", Some(44524), None), + /// Allows inferring `'static` outlives requirements (RFC 2093). + (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), + /// Allows associated types in inherent impls. + (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), /// Allow anonymous constants from an inline `const` block (incomplete, inline_const, "1.49.0", Some(76001), None), - - /// Allows unsized fn parameters. - (active, unsized_fn_params, "1.49.0", Some(48055), None), - - /// Allows the use of destructuring assignments. - (active, destructuring_assignment, "1.49.0", Some(71126), None), - - /// Enables `#[cfg(panic = "...")]` config key. - (active, cfg_panic, "1.49.0", Some(77443), None), - - /// Allows capturing disjoint fields in a closure/generator (RFC 2229). - (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), - - /// Allows const generics to have default values (e.g. `struct Foo(...);`). - (active, const_generics_defaults, "1.51.0", Some(44580), None), - - /// Allows references to types with interior mutability within constants - (active, const_refs_to_cell, "1.51.0", Some(80384), None), - /// Allows using `pointer` and `reference` in intra-doc links (active, intra_doc_pointers, "1.51.0", Some(80896), None), - - /// Allows `extern "C-cmse-nonsecure-call" fn()`. - (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None), - - /// Allows associated types in inherent impls. - (incomplete, inherent_associated_types, "1.52.0", Some(8995), None), - + /// Allows `#[instruction_set(_)]` attribute + (active, isa_attribute, "1.48.0", Some(74727), None), + /// Allows `'a: { break 'a; }`. + (active, label_break_value, "1.28.0", Some(48594), None), // Allows setting the threshold for the `large_assignments` lint. (active, large_assignments, "1.52.0", Some(83518), None), - - /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries. - (active, c_unwind, "1.52.0", Some(74990), None), - - /// Allows using `#[repr(align(...))]` on function items - (active, fn_align, "1.53.0", Some(82232), None), - - /// Allows `extern "wasm" fn` - (active, wasm_abi, "1.53.0", Some(83788), None), - - /// Allows function attribute `#[no_coverage]`, to bypass coverage - /// instrumentation of that function. - (active, no_coverage, "1.53.0", Some(84605), None), - - /// Allows trait bounds in `const fn`. - (active, const_fn_trait_bound, "1.53.0", Some(57563), None), - - /// Allows `async {}` expressions in const contexts. - (active, const_async_blocks, "1.53.0", Some(85368), None), - - /// Allows using imported `main` function - (active, imported_main, "1.53.0", Some(28937), None), - + /// Allows `if/while p && let q = r && ...` chains. + (incomplete, let_chains, "1.37.0", Some(53667), None), + /// Allows `let...else` statements. + (active, let_else, "1.56.0", Some(87335), None), + /// Allows `#[link(..., cfg(..))]`. + (active, link_cfg, "1.14.0", Some(37406), None), + /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. + (active, lint_reasons, "1.31.0", Some(54503), None), + /// Allows `#[marker]` on certain traits allowing overlapping implementations. + (active, marker_trait_attr, "1.30.0", Some(29864), None), + /// A minimal, sound subset of specialization intended to be used by the + /// standard library until the soundness issues with specialization + /// are fixed. + (active, min_specialization, "1.7.0", Some(31844), None), + /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. + (active, more_qualified_paths, "1.54.0", Some(86935), None), + /// Allows the `#[must_not_suspend]` attribute. + (active, must_not_suspend, "1.57.0", Some(83310), None), + /// Allows using `#[naked]` on functions. + (active, naked_functions, "1.9.0", Some(32408), None), /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]` (active, native_link_modifiers, "1.53.0", Some(81490), None), - + /// Allows specifying the as-needed link modifier + (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), /// Allows specifying the bundle link modifier (active, native_link_modifiers_bundle, "1.53.0", Some(81490), None), - /// Allows specifying the verbatim link modifier (active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None), - /// Allows specifying the whole-archive link modifier (active, native_link_modifiers_whole_archive, "1.53.0", Some(81490), None), - - /// Allows specifying the as-needed link modifier - (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None), - - /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. - (active, more_qualified_paths, "1.54.0", Some(86935), None), - - /// Allows `cfg(target_abi = "...")`. - (active, cfg_target_abi, "1.55.0", Some(80970), None), - - /// Infer generic args for both consts and types. - (active, generic_arg_infer, "1.55.0", Some(85077), None), - - /// Allows `#[derive(Default)]` and `#[default]` on enums. - (active, derive_default_enum, "1.56.0", Some(86985), None), - - /// Allows `for _ in _` loops in const contexts. - (active, const_for, "1.56.0", Some(87575), None), - - /// Allows the `?` operator in const contexts. - (active, const_try, "1.56.0", Some(74935), None), - + /// Allow negative trait implementations. + (active, negative_impls, "1.44.0", Some(68318), None), + /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. + (active, never_type, "1.13.0", Some(35121), None), + /// Allows diverging expressions to fall back to `!` rather than `()`. + (active, never_type_fallback, "1.41.0", Some(65992), None), + /// Allows using non lexical lifetimes (RFC 2094). + (active, nll, "1.0.0", Some(43234), None), + /// Allows `#![no_core]`. + (active, no_core, "1.3.0", Some(29639), None), + /// Allows function attribute `#[no_coverage]`, to bypass coverage + /// instrumentation of that function. + (active, no_coverage, "1.53.0", Some(84605), None), + /// Allows the use of `no_sanitize` attribute. + (active, no_sanitize, "1.42.0", Some(39699), None), + /// Allows using the `non_exhaustive_omitted_patterns` lint. + (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), + /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe. + /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and + /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. + (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), + /// Allows using `#[optimize(X)]`. + (active, optimize_attribute, "1.34.0", Some(54882), None), + /// Allows `extern "platform-intrinsic" { ... }`. + (active, platform_intrinsics, "1.4.0", Some(27731), None), + /// Allows using `#![plugin(myplugin)]`. + (active, plugin, "1.0.0", Some(29597), None), + /// Allows exhaustive integer pattern matching on `usize` and `isize`. + (active, precise_pointer_size_matching, "1.32.0", Some(56354), None), + /// Allows macro attributes on expressions, statements and non-inline modules. + (active, proc_macro_hygiene, "1.30.0", Some(54727), None), + /// Allows the use of raw-dylibs (RFC 2627). + (incomplete, raw_dylib, "1.40.0", Some(58713), None), + /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions. + (active, raw_ref_op, "1.41.0", Some(64490), None), + /// Allows using the `#[register_attr]` attribute. + (active, register_attr, "1.41.0", Some(66080), None), + /// Allows using the `#[register_tool]` attribute. + (active, register_tool, "1.41.0", Some(66079), None), + /// Allows the `#[repr(i128)]` attribute for enums. + (incomplete, repr128, "1.16.0", Some(56071), None), + /// Allows `repr(simd)` and importing the various simd intrinsics. + (active, repr_simd, "1.4.0", Some(27731), None), + /// Allows the use of SIMD types in functions declared in `extern` blocks. + (active, simd_ffi, "1.0.0", Some(27731), None), + /// Allows specialization of implementations (RFC 1210). + (incomplete, specialization, "1.7.0", Some(31844), None), + /// Allows `#[link(kind="static-nobundle"...)]`. + (active, static_nobundle, "1.16.0", Some(37403), None), + /// Allows attributes on expressions and non-item statements. + (active, stmt_expr_attributes, "1.6.0", Some(15701), None), + /// Allows the use of `#[target_feature]` on safe functions. + (active, target_feature_11, "1.45.0", Some(69098), None), + /// Allows using `#[thread_local]` on `static` items. + (active, thread_local, "1.0.0", Some(29594), None), + /// Allows defining `trait X = A + B;` alias items. + (active, trait_alias, "1.24.0", Some(41517), None), /// Allows upcasting trait objects via supertraits. /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. (incomplete, trait_upcasting, "1.56.0", Some(65991), None), - - /// Allows explicit generic arguments specification with `impl Trait` present. - (active, explicit_generic_args_with_impl_trait, "1.56.0", Some(83701), None), - - /// Allows using doc(primitive) without a future-incompat warning - (active, doc_primitive, "1.56.0", Some(88070), None), - - /// Allows non-trivial generic constants which have to have wfness manually propagated to callers - (incomplete, generic_const_exprs, "1.56.0", Some(76560), None), - - /// Allows additional const parameter types, such as `&'static str` or user defined types - (incomplete, adt_const_params, "1.56.0", Some(44580), None), - - /// Allows `let...else` statements. - (active, let_else, "1.56.0", Some(87335), None), - - /// Allows the `#[must_not_suspend]` attribute. - (active, must_not_suspend, "1.57.0", Some(83310), None), - - /// Allows `#[track_caller]` on closures and generators. - (active, closure_track_caller, "1.57.0", Some(87417), None), - - /// Allows `#[doc(cfg_hide(...))]`. - (active, doc_cfg_hide, "1.57.0", Some(43781), None), - - /// Allows using the `non_exhaustive_omitted_patterns` lint. - (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None), - + /// Allows #[repr(transparent)] on unions (RFC 2645). + (active, transparent_unions, "1.37.0", Some(60405), None), + /// Allows inconsistent bounds in where clauses. + (active, trivial_bounds, "1.28.0", Some(48214), None), + /// Allows using `try {...}` expressions. + (active, try_blocks, "1.29.0", Some(31436), None), + /// Allows `impl Trait` to be used inside type aliases (RFC 2515). + (active, type_alias_impl_trait, "1.38.0", Some(63063), None), + /// Allows the use of type ascription in expressions. + (active, type_ascription, "1.6.0", Some(23416), None), /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (incomplete, type_changing_struct_update, "1.58.0", Some(86555), None), - - /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. - (active, doc_auto_cfg, "1.58.0", Some(43781), None), - - /// Allows using `const` operands in inline assembly. - (active, asm_const, "1.58.0", Some(72016), None), - - /// Allows using `sym` operands in inline assembly. - (active, asm_sym, "1.58.0", Some(72016), None), - - /// Enables experimental inline assembly support for additional architectures. - (active, asm_experimental_arch, "1.58.0", Some(72016), None), + /// Allows unsized fn parameters. + (active, unsized_fn_params, "1.49.0", Some(48055), None), + /// Allows unsized rvalues at arguments and parameters. + (incomplete, unsized_locals, "1.30.0", Some(48055), None), + /// Allows unsized tuple coercion. + (active, unsized_tuple_coercion, "1.20.0", Some(42877), None), + /// Allows `union`s to implement `Drop`. Moreover, `union`s may now include fields + /// that don't implement `Copy` as long as they don't have any drop glue. + /// This is checked recursively. On encountering type variable where no progress can be made, + /// `T: Copy` is used as a substitute for "no drop glue". + /// + /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. + (active, untagged_unions, "1.13.0", Some(55149), None), + /// Allows `extern "wasm" fn` + (active, wasm_abi, "1.53.0", Some(83788), None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: actual feature gates diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 7b9b68268eacd..4b40040a03671 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -45,132 +45,130 @@ declare_features! ( // feature-group-start: removed features // ------------------------------------------------------------------------- - (removed, import_shadowing, "1.0.0", None, None, None), - (removed, managed_boxes, "1.0.0", None, None, None), - /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645), None, None), - (removed, reflect, "1.0.0", Some(27749), None, None), - /// A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None, None), - (removed, quad_precision_float, "1.0.0", None, None, None), - (removed, struct_inherit, "1.0.0", None, None, None), - (removed, test_removed_feature, "1.0.0", None, None, None), - (removed, visible_private_types, "1.0.0", None, None, None), - (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), - /// Allows using items which are missing stability attributes - (removed, unmarked_api, "1.0.0", None, None, None), - (removed, allocator, "1.0.0", None, None, None), - (removed, simd, "1.0.0", Some(27731), None, - Some("removed in favor of `#[repr(simd)]`")), (removed, advanced_slice_patterns, "1.0.0", Some(62254), None, Some("merged into `#![feature(slice_patterns)]`")), - (removed, macro_reexport, "1.0.0", Some(29638), None, - Some("subsumed by `pub use`")), + (removed, allocator, "1.0.0", None, None, None), + (removed, await_macro, "1.38.0", Some(50547), None, + Some("subsumed by `.await` syntax")), + /// Allows comparing raw pointers during const eval. + (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, + Some("cannot be allowed in const eval in any meaningful way")), + /// Allows non-trivial generic constants which have to be manually propagated upwards. + (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")), + /// Allows the definition of `const` functions with some advanced features. + (removed, const_fn, "1.54.0", Some(57563), None, + Some("split into finer-grained feature gates")), + /// Allows const generic types (e.g. `struct Foo(...);`). + (removed, const_generics, "1.34.0", Some(44580), None, + Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")), + /// Allows `[x; N]` where `x` is a constant (RFC 2203). + (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), None, + Some("removed due to causing promotable bugs")), + /// Allows casting raw pointers to `usize` during const eval. + (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None, + Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")), + /// Allows `T: ?const Trait` syntax in bounds. + (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None, + Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), /// Allows using custom attributes (RFC 572). (removed, custom_attribute, "1.0.0", Some(29642), None, Some("removed in favor of `#![register_tool]` and `#![register_attr]`")), - /// Allows features specific to OIBIT (now called auto traits). - /// Renamed to `auto_traits`. - (removed, optin_builtin_traits, "1.0.0", Some(13231), None, - Some("renamed to `auto_traits`")), - (removed, pushpop_unsafe, "1.2.0", None, None, None), - (removed, needs_allocator, "1.4.0", Some(27389), None, - Some("subsumed by `#![feature(allocator_internals)]`")), - /// Allows identifying crates that contain sanitizer runtimes. - (removed, sanitizer_runtime, "1.17.0", None, None, None), + /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.32.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), /// Allows `#[doc(spotlight)]`. /// The attribute was renamed to `#[doc(notable_trait)]` /// and the feature to `doc_notable_trait`. (removed, doc_spotlight, "1.22.0", Some(45040), None, Some("renamed to `doc_notable_trait`")), - (removed, proc_macro_mod, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_expr, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_non_items, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, proc_macro_gen, "1.27.0", Some(54727), None, - Some("subsumed by `#![feature(proc_macro_hygiene)]`")), - (removed, panic_implementation, "1.28.0", Some(44489), None, - Some("subsumed by `#[panic_handler]`")), - /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. - (removed, custom_derive, "1.32.0", Some(29644), None, - Some("subsumed by `#[proc_macro_derive]`")), - /// Paths of the form: `extern::foo::bar` - (removed, extern_in_paths, "1.33.0", Some(55600), None, - Some("subsumed by `::foo::bar` paths")), - (removed, quote, "1.33.0", Some(29601), None, None), - /// Allows const generic types (e.g. `struct Foo(...);`). - (removed, const_generics, "1.34.0", Some(44580), None, - Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")), - /// Allows `[x; N]` where `x` is a constant (RFC 2203). - (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), None, - Some("removed due to causing promotable bugs")), /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238). (removed, dropck_parametricity, "1.38.0", Some(28498), None, None), - (removed, await_macro, "1.38.0", Some(50547), None, - Some("subsumed by `.await` syntax")), /// Allows defining `existential type`s. (removed, existential_type, "1.38.0", Some(63063), None, Some("removed in favor of `#![feature(type_alias_impl_trait)]`")), - /// Allows using the macros: - /// + `__diagnostic_used` - /// + `__register_diagnostic` - /// +`__build_diagnostic_array` - (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), - /// Allows using `#[on_unimplemented(..)]` on traits. - /// (Moved to `rustc_attrs`.) - (removed, on_unimplemented, "1.40.0", None, None, None), - /// Allows overlapping impls of marker traits. - (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, - Some("removed in favor of `#![feature(marker_trait_attr)]`")), - /// Allows `T: ?const Trait` syntax in bounds. - (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None, - Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")), - /// Allows `#[no_debug]`. - (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + /// Paths of the form: `extern::foo::bar` + (removed, extern_in_paths, "1.33.0", Some(55600), None, + Some("subsumed by `::foo::bar` paths")), + /// Allows `#[doc(include = "some-file")]`. + (removed, external_doc, "1.54.0", Some(44732), None, + Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + /// Allows `impl Trait` in bindings (`let`, `const`, `static`). + (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None, + Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), + (removed, import_shadowing, "1.0.0", None, None, None), /// Lazily evaluate constants. This allows constants to depend on type parameters. (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")), - /// Allows comparing raw pointers during const eval. - (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None, - Some("cannot be allowed in const eval in any meaningful way")), - /// Allows non-trivial generic constants which have to be manually propagated upwards. - (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")), /// Allows using the `#[link_args]` attribute. (removed, link_args, "1.53.0", Some(29596), None, Some("removed in favor of using `-C link-arg=ARG` on command line, \ which is available from cargo build scripts with `cargo:rustc-link-arg` now")), + (removed, macro_reexport, "1.0.0", Some(29638), None, + Some("subsumed by `pub use`")), /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. (removed, main, "1.53.0", Some(29634), None, None), - (removed, pub_macro_rules, "1.53.0", Some(78855), None, - Some("removed due to being incomplete, in particular it does not work across crates")), - /// Allows the definition of `const` functions with some advanced features. - (removed, const_fn, "1.54.0", Some(57563), None, - Some("split into finer-grained feature gates")), - /// Allows using `#[plugin_registrar]` on functions. - (removed, plugin_registrar, "1.54.0", Some(29597), None, - Some("a __rustc_plugin_registrar symbol must now be defined instead")), - - /// Allows `#[doc(include = "some-file")]`. - (removed, external_doc, "1.54.0", Some(44732), None, - Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), - - /// Allows casting raw pointers to `usize` during const eval. - (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None, - Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")), - - /// Allows `impl Trait` in bindings (`let`, `const`, `static`). - (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None, - Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), - + (removed, managed_boxes, "1.0.0", None, None, None), /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), None, Some("removed in favor of full type_alias_impl_trait")), - + (removed, needs_allocator, "1.4.0", Some(27389), None, + Some("subsumed by `#![feature(allocator_internals)]`")), + /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 + (removed, negate_unsigned, "1.0.0", Some(29645), None, None), + /// Allows `#[no_debug]`. + (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), + /// Allows using `#[on_unimplemented(..)]` on traits. + /// (Moved to `rustc_attrs`.) + (removed, on_unimplemented, "1.40.0", None, None, None), + /// A way to temporarily opt out of opt in copy. This will *never* be accepted. + (removed, opt_out_copy, "1.0.0", None, None, None), + /// Allows features specific to OIBIT (now called auto traits). + /// Renamed to `auto_traits`. + (removed, optin_builtin_traits, "1.0.0", Some(13231), None, + Some("renamed to `auto_traits`")), + /// Allows overlapping impls of marker traits. + (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, + Some("removed in favor of `#![feature(marker_trait_attr)]`")), + (removed, panic_implementation, "1.28.0", Some(44489), None, + Some("subsumed by `#[panic_handler]`")), + /// Allows using `#[plugin_registrar]` on functions. + (removed, plugin_registrar, "1.54.0", Some(29597), None, + Some("a __rustc_plugin_registrar symbol must now be defined instead")), + (removed, proc_macro_expr, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_gen, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_mod, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, proc_macro_non_items, "1.27.0", Some(54727), None, + Some("subsumed by `#![feature(proc_macro_hygiene)]`")), + (removed, pub_macro_rules, "1.53.0", Some(78855), None, + Some("removed due to being incomplete, in particular it does not work across crates")), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, quad_precision_float, "1.0.0", None, None, None), + (removed, quote, "1.33.0", Some(29601), None, None), + (removed, reflect, "1.0.0", Some(27749), None, None), + /// Allows using the macros: + /// + `__diagnostic_used` + /// + `__register_diagnostic` + /// +`__build_diagnostic_array` + (removed, rustc_diagnostic_macros, "1.38.0", None, None, None), + /// Allows identifying crates that contain sanitizer runtimes. + (removed, sanitizer_runtime, "1.17.0", None, None, None), + (removed, simd, "1.0.0", Some(27731), None, + Some("removed in favor of `#[repr(simd)]`")), + (removed, struct_inherit, "1.0.0", None, None, None), + (removed, test_removed_feature, "1.0.0", None, None, None), + /// Allows using items which are missing stability attributes + (removed, unmarked_api, "1.0.0", None, None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), /// Allows `#[unwind(..)]`. /// /// Permits specifying whether a function should permit unwinding or abort on unwind. (removed, unwind_attributes, "1.56.0", Some(58760), None, Some("use the C-unwind ABI instead")), + (removed, visible_private_types, "1.0.0", None, None, None), + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! + // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way. + // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! // ------------------------------------------------------------------------- // feature-group-end: removed features diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 129237775fe3f..9ec9974e1adce 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -7,7 +7,7 @@ //! * Library features have at most one stability level. //! * Library features have at most one `since` value. //! * All unstable lang features have tests to ensure they are actually unstable. -//! * Language features in a group are sorted by `since` value. +//! * Language features in a group are sorted by feature name. use std::collections::HashMap; use std::fmt; @@ -258,7 +258,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features let mut next_feature_omits_tracking_issue = false; let mut in_feature_group = false; - let mut prev_since = None; + let mut prev_name = None; contents .lines() @@ -291,11 +291,11 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } in_feature_group = true; - prev_since = None; + prev_name = None; return None; } else if line.starts_with(FEATURE_GROUP_END_PREFIX) { in_feature_group = false; - prev_since = None; + prev_name = None; return None; } @@ -325,16 +325,16 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } }; if in_feature_group { - if prev_since > since { + if prev_name > Some(name) { tidy_error!( bad, - "{}:{}: feature {} is not sorted by \"since\" (version number)", + "{}:{}: feature {} is not sorted by feature name", path.display(), line_number, name, ); } - prev_since = since; + prev_name = Some(name); } let issue_str = parts.next().unwrap().trim(); From 2a82d1cd0c93b8d33c885734373bd7806725b37d Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 15 Nov 2021 21:11:15 -0500 Subject: [PATCH 23/29] Suggest where feature should be placed --- src/tools/tidy/src/features.rs | 45 +++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index 9ec9974e1adce..9b6037c6a4ba7 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -258,7 +258,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features let mut next_feature_omits_tracking_issue = false; let mut in_feature_group = false; - let mut prev_name = None; + let mut prev_names = vec![]; contents .lines() @@ -291,11 +291,11 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } in_feature_group = true; - prev_name = None; + prev_names = vec![]; return None; } else if line.starts_with(FEATURE_GROUP_END_PREFIX) { in_feature_group = false; - prev_name = None; + prev_names = vec![]; return None; } @@ -325,16 +325,49 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features } }; if in_feature_group { - if prev_name > Some(name) { + if prev_names.last() > Some(&name) { + // This assumes the user adds the feature name at the end of the list, as we're + // not looking ahead. + let correct_index = match prev_names.binary_search(&name) { + Ok(_) => { + // This only occurs when the feature name has already been declared. + tidy_error!( + bad, + "{}:{}: duplicate feature {}", + path.display(), + line_number, + name, + ); + // skip any additional checks for this line + return None; + } + Err(index) => index, + }; + + let correct_placement = if correct_index == 0 { + "at the beginning of the feature group".to_owned() + } else if correct_index == prev_names.len() { + // I don't believe this is reachable given the above assumption, but it + // doesn't hurt to be safe. + "at the end of the feature group".to_owned() + } else { + format!( + "between {} and {}", + prev_names[correct_index - 1], + prev_names[correct_index], + ) + }; + tidy_error!( bad, - "{}:{}: feature {} is not sorted by feature name", + "{}:{}: feature {} is not sorted by feature name (should be {})", path.display(), line_number, name, + correct_placement, ); } - prev_name = Some(name); + prev_names.push(name); } let issue_str = parts.next().unwrap().trim(); From de05d3ec31f22b1f3afaf8b5ceddf224492c4aaa Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Sat, 13 Nov 2021 11:14:17 +0000 Subject: [PATCH 24/29] Print full char literal on error if any are non-printing --- .../src/lexer/unescape_error_reporting.rs | 10 ++++++++++ .../char/whitespace-character-literal.rs | 9 +++++++++ .../char/whitespace-character-literal.stderr | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/test/ui/parser/char/whitespace-character-literal.rs create mode 100644 src/test/ui/parser/char/whitespace-character-literal.stderr diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 569f186a72766..0f6594a2a7f32 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -82,6 +82,16 @@ pub(crate) fn emit_unescape_error( Applicability::MachineApplicable, ); } + } else { + if lit.chars().filter(|x| x.is_whitespace() || x.is_control()).count() >= 1 { + handler.span_note( + span, + &format!( + "there are non-printing characters, the full sequence is `{}`", + lit.escape_default(), + ), + ); + } } if !has_help { diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs new file mode 100644 index 0000000000000..ecb5c3cf49eda --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.rs @@ -0,0 +1,9 @@ +// This tests that the error generated when a character literal has multiple +// characters in it contains a note about non-printing characters. + +fn main() { + // x + let _hair_space_around = ' x​'; + //~^ ERROR: character literal may only contain one codepoint + //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` +} diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr new file mode 100644 index 0000000000000..a12088ce77d11 --- /dev/null +++ b/src/test/ui/parser/char/whitespace-character-literal.stderr @@ -0,0 +1,18 @@ +error: character literal may only contain one codepoint + --> $DIR/whitespace-character-literal.rs:6:30 + | +LL | let _hair_space_around = ' x​'; + | ^^^^ + | +note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + --> $DIR/whitespace-character-literal.rs:6:31 + | +LL | let _hair_space_around = ' x​'; + | ^^ +help: if you meant to write a `str` literal, use double quotes + | +LL | let _hair_space_around = " x​"; + | ~~~~ + +error: aborting due to previous error + From 52199c93bb065db6e4ca5b95977212a30c646b5f Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Sat, 13 Nov 2021 12:46:22 +0000 Subject: [PATCH 25/29] Suggest removing the non-printing characters --- .../src/lexer/unescape_error_reporting.rs | 17 ++++++++++++++++- .../parser/char/whitespace-character-literal.rs | 3 ++- .../char/whitespace-character-literal.stderr | 13 ++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 0f6594a2a7f32..aa7ab4a953ca2 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -7,6 +7,10 @@ use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; +fn printing(ch: char) -> bool { + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) != 0 && !ch.is_whitespace() +} + pub(crate) fn emit_unescape_error( handler: &Handler, // interior part of the literal, without quotes @@ -83,7 +87,11 @@ pub(crate) fn emit_unescape_error( ); } } else { - if lit.chars().filter(|x| x.is_whitespace() || x.is_control()).count() >= 1 { + let printable: Vec = lit.chars().filter(|x| printing(*x)).collect(); + + if let [ch] = printable.as_slice() { + has_help = true; + handler.span_note( span, &format!( @@ -91,6 +99,13 @@ pub(crate) fn emit_unescape_error( lit.escape_default(), ), ); + + handler.span_suggestion( + span, + "consider removing the non-printing characters", + ch.to_string(), + Applicability::MaybeIncorrect, + ); } } diff --git a/src/test/ui/parser/char/whitespace-character-literal.rs b/src/test/ui/parser/char/whitespace-character-literal.rs index ecb5c3cf49eda..de5e09204b462 100644 --- a/src/test/ui/parser/char/whitespace-character-literal.rs +++ b/src/test/ui/parser/char/whitespace-character-literal.rs @@ -2,8 +2,9 @@ // characters in it contains a note about non-printing characters. fn main() { - // x let _hair_space_around = ' x​'; //~^ ERROR: character literal may only contain one codepoint //~| NOTE: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` + //~| HELP: consider removing the non-printing characters + //~| SUGGESTION: x } diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr index a12088ce77d11..aa4fe4cf01f64 100644 --- a/src/test/ui/parser/char/whitespace-character-literal.stderr +++ b/src/test/ui/parser/char/whitespace-character-literal.stderr @@ -1,18 +1,17 @@ +['x'] error: character literal may only contain one codepoint - --> $DIR/whitespace-character-literal.rs:6:30 + --> $DIR/whitespace-character-literal.rs:5:30 | LL | let _hair_space_around = ' x​'; - | ^^^^ + | ^--^ + | | + | help: consider removing the non-printing characters: `x` | note: there are non-printing characters, the full sequence is `\u{200a}x\u{200b}` - --> $DIR/whitespace-character-literal.rs:6:31 + --> $DIR/whitespace-character-literal.rs:5:31 | LL | let _hair_space_around = ' x​'; | ^^ -help: if you meant to write a `str` literal, use double quotes - | -LL | let _hair_space_around = " x​"; - | ~~~~ error: aborting due to previous error From 17b5e2d167e8dec14117f0722c72444d2e3a5b2e Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Sat, 13 Nov 2021 13:25:19 +0000 Subject: [PATCH 26/29] Remove debug output from test stderr --- src/test/ui/parser/char/whitespace-character-literal.stderr | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/parser/char/whitespace-character-literal.stderr b/src/test/ui/parser/char/whitespace-character-literal.stderr index aa4fe4cf01f64..d73de41a8099b 100644 --- a/src/test/ui/parser/char/whitespace-character-literal.stderr +++ b/src/test/ui/parser/char/whitespace-character-literal.stderr @@ -1,4 +1,3 @@ -['x'] error: character literal may only contain one codepoint --> $DIR/whitespace-character-literal.rs:5:30 | From 09e59c2875e351cacd2f9cb653fee383acf02121 Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Sat, 13 Nov 2021 15:08:20 +0000 Subject: [PATCH 27/29] Inline printable function --- .../src/lexer/unescape_error_reporting.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index aa7ab4a953ca2..7f68112a427ba 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -7,10 +7,6 @@ use rustc_errors::{pluralize, Applicability, Handler}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; -fn printing(ch: char) -> bool { - unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) != 0 && !ch.is_whitespace() -} - pub(crate) fn emit_unescape_error( handler: &Handler, // interior part of the literal, without quotes @@ -87,7 +83,13 @@ pub(crate) fn emit_unescape_error( ); } } else { - let printable: Vec = lit.chars().filter(|x| printing(*x)).collect(); + let printable: Vec = lit + .chars() + .filter(|&x| { + unicode_width::UnicodeWidthChar::width(x).unwrap_or(0) != 0 + && !x.is_whitespace() + }) + .collect(); if let [ch] = printable.as_slice() { has_help = true; From eee29b0b95aedd9568df63a49340ca6efbf4bbb0 Mon Sep 17 00:00:00 2001 From: 5225225 <5225225@mailbox.org> Date: Tue, 16 Nov 2021 08:08:31 +0000 Subject: [PATCH 28/29] Increase tidy limit for parser by 1 --- src/tools/tidy/src/ui_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index cc058d538f388..681b2486d07cc 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -9,7 +9,7 @@ const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 1102; const ISSUES_ENTRY_LIMIT: usize = 2310; -const PARSER_LIMIT: usize = 1004; +const PARSER_LIMIT: usize = 1005; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui")) From 4c32ab8eb4c1f963981eea0c3ce713d0737ded9f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Nov 2021 09:28:30 -0500 Subject: [PATCH 29/29] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index a8b976eb350ac..76a3329f51439 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a8b976eb350acec83280a0cd1ca3ac99faff67bc +Subproject commit 76a3329f51439ff2cacda4d26d478a9dc1682a06