From 8e37f0f120ba8b77889bea3fc607004c89afffb4 Mon Sep 17 00:00:00 2001 From: sysrex <769991+sysrex@users.noreply.github.com> Date: Wed, 24 Sep 2025 09:13:08 +0100 Subject: chore: remove discord references from the std library as well --- library/std/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 33e3bf0c085..9266a0af2c8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -94,7 +94,7 @@ //! pull-requests for your suggested changes. //! //! Contributions are appreciated! If you see a part of the docs that can be -//! improved, submit a PR, or chat with us first on [Discord][rust-discord] +//! improved, submit a PR, or chat with us first on [Zulip][rust-zulip] //! #docs. //! //! # A Tour of The Rust Standard Library @@ -212,7 +212,7 @@ //! [multithreading]: thread //! [other]: #what-is-in-the-standard-library-documentation //! [primitive types]: ../book/ch03-02-data-types.html -//! [rust-discord]: https://discord.gg/rust-lang +//! [rust-zulip]: https://rust-lang.zulipchat.com/ //! [array]: prim@array //! [slice]: prim@slice -- cgit 1.4.1-3-g733a5 From 5a4e53603631475335bab3e1416f4aca61172094 Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Wed, 24 Sep 2025 12:55:38 +0800 Subject: Fix infinite recursion in Path::eq with String --- library/std/src/path.rs | 12 ++++++------ library/std/tests/path.rs | 16 +++++++++++++--- 2 files changed, 19 insertions(+), 9 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 70ba502d684..88d8a4f21ca 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2107,7 +2107,7 @@ impl PartialEq for PathBuf { impl cmp::PartialEq for PathBuf { #[inline] fn eq(&self, other: &str) -> bool { - Path::eq(self, other) + self.as_path() == other } } @@ -2115,7 +2115,7 @@ impl cmp::PartialEq for PathBuf { impl cmp::PartialEq for str { #[inline] fn eq(&self, other: &PathBuf) -> bool { - other == self + self == other.as_path() } } @@ -2123,7 +2123,7 @@ impl cmp::PartialEq for str { impl cmp::PartialEq for PathBuf { #[inline] fn eq(&self, other: &String) -> bool { - **self == **other + self.as_path() == other.as_str() } } @@ -2131,7 +2131,7 @@ impl cmp::PartialEq for PathBuf { impl cmp::PartialEq for String { #[inline] fn eq(&self, other: &PathBuf) -> bool { - other == self + self.as_str() == other.as_path() } } @@ -3426,7 +3426,7 @@ impl cmp::PartialEq for str { impl cmp::PartialEq for Path { #[inline] fn eq(&self, other: &String) -> bool { - self == &*other + self == other.as_str() } } @@ -3434,7 +3434,7 @@ impl cmp::PartialEq for Path { impl cmp::PartialEq for String { #[inline] fn eq(&self, other: &Path) -> bool { - other == self + self.as_str() == other } } diff --git a/library/std/tests/path.rs b/library/std/tests/path.rs index fa76c50597b..837a14b808f 100644 --- a/library/std/tests/path.rs +++ b/library/std/tests/path.rs @@ -2528,7 +2528,17 @@ fn normalize_lexically() { } #[test] -/// See issue#146183 -fn compare_path_to_str() { - assert!(&PathBuf::from("x") == "x"); +/// See issue#146183 and issue#146940 +fn compare_path_like_to_str_like() { + let path_buf = PathBuf::from("x"); + let path = Path::new("x"); + let s = String::from("x"); + assert!(path == "x"); + assert!("x" == path); + assert!(path == &s); + assert!(&s == path); + assert!(&path_buf == "x"); + assert!("x" == &path_buf); + assert!(path_buf == s); + assert!(s == path_buf); } -- cgit 1.4.1-3-g733a5 From b2634e31c435aeff149c5660f9329a0578ad1e72 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Wed, 24 Sep 2025 12:10:15 -0500 Subject: std: add support for armv7a-vex-v5 target Co-authored-by: Lewis McClelland --- .../rustc_target/src/spec/targets/armv7a_vex_v5.rs | 2 +- library/Cargo.lock | 10 + library/std/Cargo.toml | 7 +- library/std/build.rs | 1 + library/std/src/env.rs | 2 + library/std/src/sys/alloc/mod.rs | 3 + library/std/src/sys/alloc/vexos.rs | 96 ++++ library/std/src/sys/env_consts.rs | 11 + library/std/src/sys/fs/mod.rs | 4 + library/std/src/sys/fs/vexos.rs | 615 +++++++++++++++++++++ library/std/src/sys/pal/mod.rs | 4 + library/std/src/sys/pal/vexos/mod.rs | 80 +++ library/std/src/sys/pal/vexos/time.rs | 28 + library/std/src/sys/random/mod.rs | 2 + library/std/src/sys/stdio/mod.rs | 4 + library/std/src/sys/stdio/vexos.rs | 100 ++++ library/std/src/sys/thread/mod.rs | 7 + library/std/src/sys/thread/vexos.rs | 17 + library/std/src/sys/thread_local/mod.rs | 2 + .../rustc/src/platform-support/armv7a-vex-v5.md | 26 +- src/tools/tidy/src/deps.rs | 1 + 21 files changed, 1012 insertions(+), 10 deletions(-) create mode 100644 library/std/src/sys/alloc/vexos.rs create mode 100644 library/std/src/sys/fs/vexos.rs create mode 100644 library/std/src/sys/pal/vexos/mod.rs create mode 100644 library/std/src/sys/pal/vexos/time.rs create mode 100644 library/std/src/sys/stdio/vexos.rs create mode 100644 library/std/src/sys/thread/vexos.rs (limited to 'library/std/src') diff --git a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs index e78f7839974..06dd2629775 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs +++ b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs @@ -34,7 +34,7 @@ pub(crate) fn target() -> Target { description: Some("ARMv7-A Cortex-A9 VEX V5 Brain".into()), tier: Some(3), host_tools: Some(false), - std: Some(false), + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/library/Cargo.lock b/library/Cargo.lock index e4b3839847b..47fbf5169f4 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -326,6 +326,7 @@ dependencies = [ "rustc-demangle", "std_detect", "unwind", + "vex-sdk", "wasi 0.11.1+wasi-snapshot-preview1", "wasi 0.14.4+wasi-0.2.4", "windows-targets 0.0.0", @@ -379,6 +380,15 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "vex-sdk" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89f74fce61d7a7ba1589da9634c6305a72befb7cc9150c1f872d87d8060f32b9" +dependencies = [ + "rustc-std-workspace-core", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index d28a7f0b460..b4d349d66de 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -62,7 +62,7 @@ path = "../windows_targets" rand = { version = "0.9.0", default-features = false, features = ["alloc"] } rand_xorshift = "0.4.0" -[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] +[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies] dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] @@ -89,6 +89,11 @@ wasip2 = { version = '0.14.4', features = [ r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] } r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] } +[target.'cfg(target_os = "vexos")'.dependencies] +vex-sdk = { version = "0.27.0", features = [ + 'rustc-dep-of-std', +], default-features = false } + [features] backtrace = [ 'addr2line/rustc-dep-of-std', diff --git a/library/std/build.rs b/library/std/build.rs index ef695601a44..8a5a785060c 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -52,6 +52,7 @@ fn main() { || target_os == "rtems" || target_os == "nuttx" || target_os == "cygwin" + || target_os == "vexos" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/env.rs b/library/std/src/env.rs index e457cd61c75..6d716bd8544 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -1098,6 +1098,7 @@ pub mod consts { /// * `"redox"` /// * `"solaris"` /// * `"solid_asp3` + /// * `"vexos"` /// * `"vita"` /// * `"vxworks"` /// * `"xous"` @@ -1148,6 +1149,7 @@ pub mod consts { /// ///
Full list of possible values /// + /// * `"bin"` /// * `"exe"` /// * `"efi"` /// * `"js"` diff --git a/library/std/src/sys/alloc/mod.rs b/library/std/src/sys/alloc/mod.rs index 6d4b09494a3..2045b2fecc6 100644 --- a/library/std/src/sys/alloc/mod.rs +++ b/library/std/src/sys/alloc/mod.rs @@ -92,6 +92,9 @@ cfg_select! { target_os = "uefi" => { mod uefi; } + target_os = "vexos" => { + mod vexos; + } target_family = "wasm" => { mod wasm; } diff --git a/library/std/src/sys/alloc/vexos.rs b/library/std/src/sys/alloc/vexos.rs new file mode 100644 index 00000000000..c1fb6896a89 --- /dev/null +++ b/library/std/src/sys/alloc/vexos.rs @@ -0,0 +1,96 @@ +// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint +#![allow(static_mut_refs)] + +use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::ptr; +use crate::sync::atomic::{AtomicBool, Ordering}; + +// Symbols for heap section boundaries defined in the target's linkerscript +unsafe extern "C" { + static mut __heap_start: u8; + static mut __heap_end: u8; +} + +static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new_with_allocator(Vexos); + +struct Vexos; + +unsafe impl dlmalloc::Allocator for Vexos { + /// Allocs system resources + fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) { + static INIT: AtomicBool = AtomicBool::new(false); + + if !INIT.swap(true, Ordering::Relaxed) { + // This target has no growable heap, as user memory has a fixed + // size/location and VEXos does not manage allocation for us. + unsafe { + ( + (&raw mut __heap_start).cast::(), + (&raw const __heap_end).offset_from_unsigned(&raw const __heap_start), + 0, + ) + } + } else { + (ptr::null_mut(), 0, 0) + } + } + + fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 { + ptr::null_mut() + } + + fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool { + false + } + + fn free(&self, _ptr: *mut u8, _size: usize) -> bool { + return false; + } + + fn can_release_part(&self, _flags: u32) -> bool { + false + } + + fn allocates_zeros(&self) -> bool { + false + } + + fn page_size(&self) -> usize { + 0x1000 + } +} + +#[stable(feature = "alloc_system_type", since = "1.28.0")] +unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling malloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.malloc(layout.size(), layout.align()) } + } + + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling calloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.calloc(layout.size(), layout.align()) } + } + + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling free() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) } + } + + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + // SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which + // guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used. + // Calling realloc() is safe because preconditions on this function match the trait method preconditions. + unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) } + } +} diff --git a/library/std/src/sys/env_consts.rs b/library/std/src/sys/env_consts.rs index 711ba0a5f8a..573f540483b 100644 --- a/library/std/src/sys/env_consts.rs +++ b/library/std/src/sys/env_consts.rs @@ -323,6 +323,17 @@ pub mod os { pub const EXE_EXTENSION: &str = "efi"; } +#[cfg(target_os = "vexos")] +pub mod os { + pub const FAMILY: &str = ""; + pub const OS: &str = "vexos"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ""; + pub const DLL_EXTENSION: &str = ""; + pub const EXE_SUFFIX: &str = ".bin"; + pub const EXE_EXTENSION: &str = "bin"; +} + #[cfg(target_os = "visionos")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index 0276bf6e64c..64f5a6b36d3 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -35,6 +35,10 @@ cfg_select! { mod uefi; use uefi as imp; } + target_os = "vexos" => { + mod vexos; + use vexos as imp; + } target_os = "wasi" => { mod wasi; use wasi as imp; diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs new file mode 100644 index 00000000000..f642e7cb074 --- /dev/null +++ b/library/std/src/sys/fs/vexos.rs @@ -0,0 +1,615 @@ +use crate::ffi::{OsString, c_char}; +use crate::fmt; +use crate::fs::TryLockError; +use crate::hash::Hash; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; +use crate::path::{Path, PathBuf}; +use crate::sys::common::small_c_string::run_path_with_cstr; +use crate::sys::time::SystemTime; +use crate::sys::{unsupported, unsupported_err}; + +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_fs; +pub use unsupported_fs::{ + DirBuilder, FileTimes, canonicalize, link, readlink, remove_dir_all, rename, rmdir, symlink, + unlink, +}; + +/// VEXos file descriptor. +/// +/// This stores an opaque pointer to a [FatFs file object structure] managed by VEXos +/// representing an open file on disk. +/// +/// [FatFs file object structure]: https://github.com/Xilinx/embeddedsw/blob/master/lib/sw_services/xilffs/src/include/ff.h?rgh-link-date=2025-09-23T20%3A03%3A43Z#L215 +/// +/// # Safety +/// +/// Since this platform uses a pointer to to an internal filesystem structure with a lifetime +/// associated with it (rather than a UNIX-style file descriptor table), care must be taken to +/// ensure that the pointer held by `FileDesc` is valid for as long as it exists. +#[derive(Debug)] +struct FileDesc(*mut vex_sdk::FIL); + +// SAFETY: VEXos's FDs can be used on a thread other than the one they were created on. +unsafe impl Send for FileDesc {} +// SAFETY: We assume an environment without threads (i.e. no RTOS). +// (If there were threads, it is possible that a mutex would be required.) +unsafe impl Sync for FileDesc {} + +pub struct File { + fd: FileDesc, +} + +#[derive(Clone)] +pub enum FileAttr { + Dir, + File { size: u64 }, +} + +pub struct ReadDir(!); + +pub struct DirEntry { + path: PathBuf, +} + +#[derive(Clone, Debug)] +pub struct OpenOptions { + read: bool, + write: bool, + append: bool, + truncate: bool, + create: bool, + create_new: bool, +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FilePermissions {} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct FileType { + is_dir: bool, +} + +impl FileAttr { + pub fn size(&self) -> u64 { + match self { + Self::File { size } => *size, + Self::Dir => 0, + } + } + + pub fn perm(&self) -> FilePermissions { + FilePermissions {} + } + + pub fn file_type(&self) -> FileType { + FileType { is_dir: matches!(self, FileAttr::Dir) } + } + + pub fn modified(&self) -> io::Result { + unsupported() + } + + pub fn accessed(&self) -> io::Result { + unsupported() + } + + pub fn created(&self) -> io::Result { + unsupported() + } +} + +impl FilePermissions { + pub fn readonly(&self) -> bool { + false + } + + pub fn set_readonly(&mut self, _readonly: bool) { + panic!("Perimissions do not exist") + } +} + +impl FileType { + pub fn is_dir(&self) -> bool { + self.is_dir + } + + pub fn is_file(&self) -> bool { + !self.is_dir + } + + pub fn is_symlink(&self) -> bool { + // No symlinks in VEXos - entries are either files or directories. + false + } +} + +impl fmt::Debug for ReadDir { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0 + } +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option> { + self.0 + } +} + +impl DirEntry { + pub fn path(&self) -> PathBuf { + self.path.clone() + } + + pub fn file_name(&self) -> OsString { + self.path.file_name().unwrap_or_default().into() + } + + pub fn metadata(&self) -> io::Result { + stat(&self.path) + } + + pub fn file_type(&self) -> io::Result { + Ok(self.metadata()?.file_type()) + } +} + +impl OpenOptions { + pub fn new() -> OpenOptions { + OpenOptions { + read: false, + write: false, + append: false, + truncate: false, + create: false, + create_new: false, + } + } + + pub fn read(&mut self, read: bool) { + self.read = read; + } + pub fn write(&mut self, write: bool) { + self.write = write; + } + pub fn append(&mut self, append: bool) { + self.append = append; + } + pub fn truncate(&mut self, truncate: bool) { + self.truncate = truncate; + } + pub fn create(&mut self, create: bool) { + self.create = create; + } + pub fn create_new(&mut self, create_new: bool) { + self.create_new = create_new; + } +} + +impl File { + pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { + run_path_with_cstr(path, &|path| { + // Enforce the invariants of `create_new`/`create`. + // + // Since VEXos doesn't have anything akin to POSIX's `oflags`, we need to enforce + // the requirements that `create_new` can't have an existing file and `!create` + // doesn't create a file ourselves. + if !opts.read && (opts.write || opts.append) && (opts.create_new || !opts.create) { + let status = unsafe { vex_sdk::vexFileStatus(path.as_ptr()) }; + + if opts.create_new && status != 0 { + return Err(io::const_error!(io::ErrorKind::AlreadyExists, "file exists",)); + } else if !opts.create && status == 0 { + return Err(io::const_error!( + io::ErrorKind::NotFound, + "no such file or directory", + )); + } + } + + let file = match opts { + // read + write - unsupported + OpenOptions { read: true, write: true, .. } => { + return Err(io::const_error!( + io::ErrorKind::InvalidInput, + "opening files with read and write access is unsupported on this target", + )); + } + + // read + OpenOptions { + read: true, + write: false, + append: _, + truncate: false, + create: false, + create_new: false, + } => unsafe { vex_sdk::vexFileOpen(path.as_ptr(), c"".as_ptr()) }, + + // append + OpenOptions { + read: false, + write: _, + append: true, + truncate: false, + create: _, + create_new: _, + } => unsafe { vex_sdk::vexFileOpenWrite(path.as_ptr()) }, + + // write + OpenOptions { + read: false, + write: true, + append: false, + truncate, + create: _, + create_new: _, + } => unsafe { + if *truncate { + vex_sdk::vexFileOpenCreate(path.as_ptr()) + } else { + // Open in append, but jump to the start of the file. + let fd = vex_sdk::vexFileOpenWrite(path.as_ptr()); + vex_sdk::vexFileSeek(fd, 0, 0); + fd + } + }, + + _ => { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid argument")); + } + }; + + if file.is_null() { + Err(io::const_error!(io::ErrorKind::NotFound, "could not open file")) + } else { + Ok(Self { fd: FileDesc(file) }) + } + }) + } + + pub fn file_attr(&self) -> io::Result { + // `vexFileSize` returns -1 upon error, so u64::try_from will fail on error. + if let Ok(size) = u64::try_from(unsafe { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + vex_sdk::vexFileSize(self.fd.0) + }) { + Ok(FileAttr::File { size }) + } else { + Err(io::const_error!(io::ErrorKind::InvalidData, "failed to get file size")) + } + } + + pub fn fsync(&self) -> io::Result<()> { + self.flush() + } + + pub fn datasync(&self) -> io::Result<()> { + self.flush() + } + + pub fn lock(&self) -> io::Result<()> { + unsupported() + } + + pub fn lock_shared(&self) -> io::Result<()> { + unsupported() + } + + pub fn try_lock(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) + } + + pub fn try_lock_shared(&self) -> Result<(), TryLockError> { + Err(TryLockError::Error(unsupported_err())) + } + + pub fn unlock(&self) -> io::Result<()> { + unsupported() + } + + pub fn truncate(&self, _size: u64) -> io::Result<()> { + unsupported() + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + let len = buf.len() as u32; + let buf_ptr = buf.as_mut_ptr(); + let read = unsafe { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + vex_sdk::vexFileRead(buf_ptr.cast::(), 1, len, self.fd.0) + }; + + if read < 0 { + Err(io::const_error!(io::ErrorKind::Other, "could not read from file")) + } else { + Ok(read as usize) + } + } + + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|b| self.read(b), bufs) + } + + #[inline] + pub fn is_read_vectored(&self) -> bool { + false + } + + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + crate::io::default_read_buf(|b| self.read(b), cursor) + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + let len = buf.len() as u32; + let buf_ptr = buf.as_ptr(); + let written = unsafe { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + vex_sdk::vexFileWrite(buf_ptr.cast_mut().cast::(), 1, len, self.fd.0) + }; + + if written < 0 { + Err(io::const_error!(io::ErrorKind::Other, "could not write to file")) + } else { + Ok(written as usize) + } + } + + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + crate::io::default_write_vectored(|b| self.write(b), bufs) + } + + #[inline] + pub fn is_write_vectored(&self) -> bool { + false + } + + pub fn flush(&self) -> io::Result<()> { + unsafe { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + vex_sdk::vexFileSync(self.fd.0); + } + Ok(()) + } + + pub fn tell(&self) -> io::Result { + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + let position = unsafe { vex_sdk::vexFileTell(self.fd.0) }; + + position.try_into().map_err(|_| { + io::const_error!(io::ErrorKind::InvalidData, "failed to get current location in file") + }) + } + + pub fn size(&self) -> Option> { + None + } + + pub fn seek(&self, pos: SeekFrom) -> io::Result { + const SEEK_SET: i32 = 0; + const SEEK_CUR: i32 = 1; + const SEEK_END: i32 = 2; + + fn try_convert_offset>(offset: T) -> io::Result { + offset.try_into().map_err(|_| { + io::const_error!( + io::ErrorKind::InvalidInput, + "cannot seek to an offset too large to fit in a 32 bit integer", + ) + }) + } + + // SAFETY: `self.fd` contains a valid pointer to `FIL` for this struct's lifetime. + match pos { + SeekFrom::Start(offset) => unsafe { + map_fresult(vex_sdk::vexFileSeek(self.fd.0, try_convert_offset(offset)?, SEEK_SET))? + }, + SeekFrom::End(offset) => unsafe { + if offset >= 0 { + map_fresult(vex_sdk::vexFileSeek( + self.fd.0, + try_convert_offset(offset)?, + SEEK_END, + ))? + } else { + // `vexFileSeek` does not support seeking with negative offset, meaning + // we have to calculate the offset from the end of the file ourselves. + + // Seek to the end of the file to get the end position in the open buffer. + map_fresult(vex_sdk::vexFileSeek(self.fd.0, 0, SEEK_END))?; + let end_position = self.tell()?; + + map_fresult(vex_sdk::vexFileSeek( + self.fd.0, + // NOTE: Files internally use a 32-bit representation for stream + // position, so `end_position as i64` should never overflow. + try_convert_offset(end_position as i64 + offset)?, + SEEK_SET, + ))? + } + }, + SeekFrom::Current(offset) => unsafe { + if offset >= 0 { + map_fresult(vex_sdk::vexFileSeek( + self.fd.0, + try_convert_offset(offset)?, + SEEK_CUR, + ))? + } else { + // `vexFileSeek` does not support seeking with negative offset, meaning + // we have to calculate the offset from the stream position ourselves. + map_fresult(vex_sdk::vexFileSeek( + self.fd.0, + try_convert_offset((self.tell()? as i64) + offset)?, + SEEK_SET, + ))? + } + }, + } + + Ok(self.tell()?) + } + + pub fn duplicate(&self) -> io::Result { + unsupported() + } + + pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { + unsupported() + } + + pub fn set_times(&self, _times: FileTimes) -> io::Result<()> { + unsupported() + } +} + +impl fmt::Debug for File { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("File").field("fd", &self.fd.0).finish() + } +} +impl Drop for File { + fn drop(&mut self) { + unsafe { vex_sdk::vexFileClose(self.fd.0) }; + } +} + +pub fn readdir(_p: &Path) -> io::Result { + // While there *is* a userspace function for reading file directories, + // the necessary implementation cannot currently be done cleanly, as + // VEXos does not expose directory length to user programs. + // + // This means that we would need to create a large fixed-length buffer + // and hope that the folder's contents didn't exceed that buffer's length, + // which obviously isn't behavior we want to rely on in the standard library. + unsupported() +} + +pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { + unsupported() +} + +pub fn exists(path: &Path) -> io::Result { + run_path_with_cstr(path, &|path| Ok(unsafe { vex_sdk::vexFileStatus(path.as_ptr()) } != 0)) +} + +pub fn stat(p: &Path) -> io::Result { + // `vexFileStatus` returns 3 if the given path is a directory, 1 if the path is a + // file, or 0 if no such path exists. + const FILE_STATUS_DIR: u32 = 3; + + run_path_with_cstr(p, &|c_path| { + let file_type = unsafe { vex_sdk::vexFileStatus(c_path.as_ptr()) }; + + // We can't get the size if its a directory because we cant open it as a file + if file_type == FILE_STATUS_DIR { + Ok(FileAttr::Dir) + } else { + let mut opts = OpenOptions::new(); + opts.read(true); + let file = File::open(p, &opts)?; + file.file_attr() + } + }) +} + +pub fn lstat(p: &Path) -> io::Result { + // Symlinks aren't supported in this filesystem + stat(p) +} + +// Cannot use `copy` from `common` here, since `File::set_permissions` is unsupported on this target. +pub fn copy(from: &Path, to: &Path) -> io::Result { + use crate::fs::File; + + // NOTE: If `from` is a directory, this call should fail due to vexFileOpen* returning null. + let mut reader = File::open(from)?; + let mut writer = File::create(to)?; + + io::copy(&mut reader, &mut writer) +} + +fn map_fresult(fresult: vex_sdk::FRESULT) -> io::Result<()> { + // VEX uses a derivative of FatFs (Xilinx's xilffs library) for filesystem operations. + match fresult { + vex_sdk::FRESULT::FR_OK => Ok(()), + vex_sdk::FRESULT::FR_DISK_ERR => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "internal function reported an unrecoverable hard error", + )), + vex_sdk::FRESULT::FR_INT_ERR => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "internal error in filesystem runtime", + )), + vex_sdk::FRESULT::FR_NOT_READY => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "the storage device could not be prepared to work", + )), + vex_sdk::FRESULT::FR_NO_FILE => Err(io::const_error!( + io::ErrorKind::NotFound, + "could not find the file in the directory" + )), + vex_sdk::FRESULT::FR_NO_PATH => Err(io::const_error!( + io::ErrorKind::NotFound, + "a directory in the path name could not be found", + )), + vex_sdk::FRESULT::FR_INVALID_NAME => Err(io::const_error!( + io::ErrorKind::InvalidInput, + "the given string is invalid as a path name", + )), + vex_sdk::FRESULT::FR_DENIED => Err(io::const_error!( + io::ErrorKind::PermissionDenied, + "the required access for this operation was denied", + )), + vex_sdk::FRESULT::FR_EXIST => Err(io::const_error!( + io::ErrorKind::AlreadyExists, + "an object with the same name already exists in the directory", + )), + vex_sdk::FRESULT::FR_INVALID_OBJECT => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "invalid or null file/directory object", + )), + vex_sdk::FRESULT::FR_WRITE_PROTECTED => Err(io::const_error!( + io::ErrorKind::PermissionDenied, + "a write operation was performed on write-protected media", + )), + vex_sdk::FRESULT::FR_INVALID_DRIVE => Err(io::const_error!( + io::ErrorKind::InvalidInput, + "an invalid drive number was specified in the path name", + )), + vex_sdk::FRESULT::FR_NOT_ENABLED => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "work area for the logical drive has not been registered", + )), + vex_sdk::FRESULT::FR_NO_FILESYSTEM => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "valid FAT volume could not be found on the drive", + )), + vex_sdk::FRESULT::FR_MKFS_ABORTED => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "failed to create filesystem volume" + )), + vex_sdk::FRESULT::FR_TIMEOUT => Err(io::const_error!( + io::ErrorKind::TimedOut, + "the function was canceled due to a timeout of thread-safe control", + )), + vex_sdk::FRESULT::FR_LOCKED => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "the operation to the object was rejected by file sharing control", + )), + vex_sdk::FRESULT::FR_NOT_ENOUGH_CORE => { + Err(io::const_error!(io::ErrorKind::OutOfMemory, "not enough memory for the operation")) + } + vex_sdk::FRESULT::FR_TOO_MANY_OPEN_FILES => Err(io::const_error!( + io::ErrorKind::Uncategorized, + "maximum number of open files has been reached", + )), + vex_sdk::FRESULT::FR_INVALID_PARAMETER => { + Err(io::const_error!(io::ErrorKind::InvalidInput, "a given parameter was invalid")) + } + _ => unreachable!(), // C-style enum + } +} diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index 513121c6d30..dd5e83ee570 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -45,6 +45,10 @@ cfg_select! { mod trusty; pub use self::trusty::*; } + target_os = "vexos" => { + mod vexos; + pub use self::vexos::*; + } all(target_os = "wasi", target_env = "p2") => { mod wasip2; pub use self::wasip2::*; diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs new file mode 100644 index 00000000000..61a34b0f68a --- /dev/null +++ b/library/std/src/sys/pal/vexos/mod.rs @@ -0,0 +1,80 @@ +#[path = "../unsupported/os.rs"] +pub mod os; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +pub mod time; + +#[expect(dead_code)] +#[path = "../unsupported/common.rs"] +mod unsupported_common; + +pub use unsupported_common::{ + decode_error_kind, init, is_interrupted, unsupported, unsupported_err, +}; + +use crate::arch::global_asm; +use crate::ptr; +use crate::sys::stdio; +use crate::time::{Duration, Instant}; + +global_asm!( + r#" + .section .boot, "ax" + .global _boot + + _boot: + ldr sp, =__stack_top @ Set up the user stack. + b _start @ Jump to the Rust entrypoint. + "# +); + +#[cfg(not(test))] +#[unsafe(no_mangle)] +pub unsafe extern "C" fn _start() -> ! { + unsafe extern "C" { + static mut __bss_start: u8; + static mut __bss_end: u8; + + fn main() -> i32; + } + + // Clear the .bss (uninitialized statics) section by filling it with zeroes. + // This is required, since the compiler assumes it will be zeroed on first access. + ptr::write_bytes( + &raw mut __bss_start, + 0, + (&raw mut __bss_end).offset_from_unsigned(&raw mut __bss_start), + ); + + main(); + + cleanup(); + abort_internal() +} + +// SAFETY: must be called only once during runtime cleanup. +// NOTE: this is not guaranteed to run, for example when the program aborts. +pub unsafe fn cleanup() { + let exit_time = Instant::now(); + const FLUSH_TIMEOUT: Duration = Duration::from_millis(15); + + // Force the serial buffer to flush + while exit_time.elapsed() < FLUSH_TIMEOUT { + vex_sdk::vexTasksRun(); + + // If the buffer has been fully flushed, exit the loop + if vex_sdk::vexSerialWriteFree(stdio::STDIO_CHANNEL) == (stdio::STDOUT_BUF_SIZE as i32) { + break; + } + } +} + +pub fn abort_internal() -> ! { + unsafe { + vex_sdk::vexSystemExitRequest(); + + loop { + vex_sdk::vexTasksRun(); + } + } +} diff --git a/library/std/src/sys/pal/vexos/time.rs b/library/std/src/sys/pal/vexos/time.rs new file mode 100644 index 00000000000..f95d96cd27a --- /dev/null +++ b/library/std/src/sys/pal/vexos/time.rs @@ -0,0 +1,28 @@ +use crate::time::Duration; + +#[expect(dead_code)] +#[path = "../unsupported/time.rs"] +mod unsupported_time; +pub use unsupported_time::{SystemTime, UNIX_EPOCH}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +impl Instant { + pub fn now() -> Instant { + let micros = unsafe { vex_sdk::vexSystemHighResTimeGet() }; + Self(Duration::from_micros(micros)) + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub(*other)?)) + } +} diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index 1e0eec07b50..3c5a4c82a9f 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -101,6 +101,7 @@ cfg_select! { any( all(target_family = "wasm", target_os = "unknown"), target_os = "xous", + target_os = "vexos", ) => { // FIXME: finally remove std support for wasm32-unknown-unknown // FIXME: add random data generation to xous @@ -116,6 +117,7 @@ cfg_select! { all(target_family = "wasm", target_os = "unknown"), all(target_os = "wasi", target_env = "p2"), target_os = "xous", + target_os = "vexos", )))] pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; diff --git a/library/std/src/sys/stdio/mod.rs b/library/std/src/sys/stdio/mod.rs index 7436e4d9de4..404ac877926 100644 --- a/library/std/src/sys/stdio/mod.rs +++ b/library/std/src/sys/stdio/mod.rs @@ -29,6 +29,10 @@ cfg_select! { mod uefi; pub use uefi::*; } + target_os = "vexos" => { + mod vexos; + pub use vexos::*; + } all(target_os = "wasi", target_env = "p1") => { mod wasip1; pub use wasip1::*; diff --git a/library/std/src/sys/stdio/vexos.rs b/library/std/src/sys/stdio/vexos.rs new file mode 100644 index 00000000000..1f2251c6421 --- /dev/null +++ b/library/std/src/sys/stdio/vexos.rs @@ -0,0 +1,100 @@ +use crate::io; + +pub struct Stdin; +pub struct Stdout; +pub type Stderr = Stdout; + +pub const STDIO_CHANNEL: u32 = 1; + +impl Stdin { + pub const fn new() -> Stdin { + Stdin + } +} + +impl io::Read for Stdin { + fn read(&mut self, mut buf: &mut [u8]) -> io::Result { + let mut count = 0; + + for out_byte in buf.iter_mut() { + let byte = unsafe { vex_sdk::vexSerialReadChar(STDIO_CHANNEL) }; + if byte < 0 { + break; + } + + *out_byte = byte as u8; + count += 1; + } + + Ok(count) + } +} + +impl Stdout { + pub const fn new() -> Stdout { + Stdout + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + let mut written = 0; + + // HACK: VEXos holds an internal ringbuffer for serial writes that is flushed to USB1 + // roughly every millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we + // must block until that buffer is flushed to USB1 before writing the rest of `buf`. + // + // This is fairly nonstandard for a `write` implementation, but it avoids a guaranteed + // recursive panic when using macros such as `print!` to write large amounts of data + // (buf.len() > 2048) to stdout at once. + for chunk in buf.chunks(STDOUT_BUF_SIZE) { + if unsafe { vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize } < chunk.len() { + self.flush().unwrap(); + } + + let count: usize = unsafe { + vex_sdk::vexSerialWriteBuffer(STDIO_CHANNEL, chunk.as_ptr(), chunk.len() as u32) + } + .try_into() + .map_err(|_| { + io::const_error!(io::ErrorKind::Uncategorized, "internal write error occurred") + })?; + + written += count; + + // This is a sanity check to ensure that we don't end up with non-contiguous + // buffer writes. e.g. a chunk gets only partially written, but we continue + // attempting to write the remaining chunks. + // + // In practice, this should never really occur since the previous flush ensures + // enough space in FIFO to write the entire chunk to vexSerialWriteBuffer. + if count != chunk.len() { + break; + } + } + + Ok(written) + } + + fn flush(&mut self) -> io::Result<()> { + // This may block for up to a millisecond. + unsafe { + while (vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize) != STDOUT_BUF_SIZE { + vex_sdk::vexTasksRun(); + } + } + + Ok(()) + } +} + +pub const STDIN_BUF_SIZE: usize = 4096; +pub const STDOUT_BUF_SIZE: usize = 2048; + +pub fn is_ebadf(_err: &io::Error) -> bool { + false +} + +pub fn panic_output() -> Option { + Some(Stdout::new()) +} diff --git a/library/std/src/sys/thread/mod.rs b/library/std/src/sys/thread/mod.rs index 6bb7fc1a20e..3bd83dd760a 100644 --- a/library/std/src/sys/thread/mod.rs +++ b/library/std/src/sys/thread/mod.rs @@ -81,6 +81,13 @@ cfg_select! { ))] pub use unsupported::set_name; } + target_os = "vexos" => { + mod vexos; + pub use vexos::{sleep, yield_now}; + #[expect(dead_code)] + mod unsupported; + pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE}; + } all(target_os = "wasi", target_env = "p1") => { mod wasip1; pub use wasip1::{DEFAULT_MIN_STACK_SIZE, sleep, yield_now}; diff --git a/library/std/src/sys/thread/vexos.rs b/library/std/src/sys/thread/vexos.rs new file mode 100644 index 00000000000..d917dde4d0b --- /dev/null +++ b/library/std/src/sys/thread/vexos.rs @@ -0,0 +1,17 @@ +use crate::time::{Duration, Instant}; + +pub fn yield_now() { + unsafe { + vex_sdk::vexTasksRun(); + } +} + +pub fn sleep(dur: Duration) { + let start = Instant::now(); + + while start.elapsed() < dur { + unsafe { + vex_sdk::vexTasksRun(); + } + } +} diff --git a/library/std/src/sys/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs index cff74857c47..d5c795093cf 100644 --- a/library/std/src/sys/thread_local/mod.rs +++ b/library/std/src/sys/thread_local/mod.rs @@ -29,6 +29,7 @@ cfg_select! { target_os = "uefi", target_os = "zkvm", target_os = "trusty", + target_os = "vexos", ) => { mod no_threads; pub use no_threads::{EagerStorage, LazyStorage, thread_local_inner}; @@ -98,6 +99,7 @@ pub(crate) mod guard { target_os = "uefi", target_os = "zkvm", target_os = "trusty", + target_os = "vexos", ) => { pub(crate) fn enable() { // FIXME: Right now there is no concept of "thread exit" on diff --git a/src/doc/rustc/src/platform-support/armv7a-vex-v5.md b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md index a7da1b16f7e..3677f8931dd 100644 --- a/src/doc/rustc/src/platform-support/armv7a-vex-v5.md +++ b/src/doc/rustc/src/platform-support/armv7a-vex-v5.md @@ -4,7 +4,7 @@ Allows compiling user programs for the [VEX V5 Brain](https://www.vexrobotics.com/276-4810.html), a microcontroller for educational and competitive robotics. -Rust support for this target is not affiliated with VEX Robotics or IFI. +Rust support for this target is not affiliated with VEX Robotics or IFI, and does not link to any official VEX SDK. ## Target maintainers @@ -17,11 +17,24 @@ This target is maintained by members of the [vexide](https://github.com/vexide) ## Requirements -This target is cross-compiled and currently requires `#![no_std]`. Dynamic linking is unsupported. +This target is cross-compiled. Dynamic linking is unsupported. -When compiling for this target, the "C" calling convention maps to AAPCS with VFP registers (hard float ABI) and the "system" calling convention maps to AAPCS without VFP registers (soft float ABI). +`#![no_std]` crates can be built using `build-std` to build `core` and `panic_abort` and optionally `alloc`. Unwinding panics are not yet supported on this target. -This target generates binaries in the ELF format that may uploaded to the brain with external tools. +`std` has only partial support due platform limitations. Notably: +- `std::process` and `std::net` are unimplemented. `std::thread` only supports sleeping and yielding, as this is a single-threaded environment. +- `std::time` has full support for `Instant`, but no support for `SystemTime`. +- `std::io` has full support for `stdin`/`stdout`/`stderr`. `stdout` and `stderr` both write to to USB channel 1 on this platform and are not differentiated. +- `std::fs` has limited support for reading or writing to files. Directory operations, file deletion, and some file opening features are unsupported and will return errors. +- A global allocator implemented on top of `dlmalloc` is provided. +- Modules that do not need to interact with the OS beyond allocation such as `std::collections`, `std::hash`, `std::future`, `std::sync`, etc are fully supported. +- Random number generation and hashing is insecure, as there is no reliable source of entropy on this platform. + +In order to support some APIs, users are expected to provide a supporting runtime SDK for `libstd` to link against. This library may be provided either by [`vex-sdk-build`](https://github.com/vexide/vex-sdk/tree/main/packages/vex-sdk-build) (which will download an official SDK from VEX) or through an open-source implementation such as [`vex-sdk-jumptable`](https://crates.io/crates/vex-sdk-jumptable). + +When compiling for this target, the "C" calling convention maps to AAPCS with VFP registers (hard float ABI) and the "system" calling convention maps to AAPCS without VFP registers (softfp ABI). + +This target generates binaries in the ELF format that may be uploaded to the brain with external tools. ## Building the target @@ -29,10 +42,7 @@ You can build Rust with support for this target by adding it to the `target` lis ## 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 `core` by using -`build-std` or similar. +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 `core` by using `build-std` or similar. When the compiler builds a binary, an ELF build artifact will be produced. Additional tools are required for this artifact to be recognizable to VEXos as a user program. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 568ec0c1198..7c5f823b57c 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -575,6 +575,7 @@ const PERMITTED_STDLIB_DEPENDENCIES: &[&str] = &[ "rustc-literal-escaper", "shlex", "unwinding", + "vex-sdk", "wasi", "windows-sys", "windows-targets", -- cgit 1.4.1-3-g733a5 From a00f24116e9bcecc8c73f9f7ec0c399964b37a92 Mon Sep 17 00:00:00 2001 From: Jeremy Smart Date: Thu, 18 Sep 2025 15:02:49 -0400 Subject: unstably constify float mul_add methods Co-authored-by: Ralf Jung --- .../rustc_const_eval/src/interpret/intrinsics.rs | 46 ++++++++++++++++++++++ compiler/rustc_const_eval/src/interpret/machine.rs | 8 ++++ library/core/src/intrinsics/mod.rs | 16 ++++---- library/core/src/num/f128.rs | 3 +- library/core/src/num/f16.rs | 3 +- library/core/src/num/f32.rs | 3 +- library/core/src/num/f64.rs | 3 +- library/coretests/tests/floats/f128.rs | 18 --------- library/coretests/tests/floats/f16.rs | 18 --------- library/coretests/tests/floats/f32.rs | 21 ---------- library/coretests/tests/floats/f64.rs | 21 ---------- library/coretests/tests/floats/mod.rs | 39 +++++++++++++++++- library/coretests/tests/lib.rs | 1 + library/std/src/lib.rs | 1 + library/std/src/num/f32.rs | 3 +- library/std/src/num/f64.rs | 3 +- src/tools/miri/src/intrinsics/math.rs | 41 ------------------- src/tools/miri/src/machine.rs | 5 +++ 18 files changed, 118 insertions(+), 135 deletions(-) delete mode 100644 library/coretests/tests/floats/f32.rs delete mode 100644 library/coretests/tests/floats/f64.rs (limited to 'library/std/src') diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 418dd658121..785978b4d71 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -636,6 +636,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { dest, rustc_apfloat::Round::NearestTiesToEven, )?, + sym::fmaf16 => self.fma_intrinsic::(args, dest)?, + sym::fmaf32 => self.fma_intrinsic::(args, dest)?, + sym::fmaf64 => self.fma_intrinsic::(args, dest)?, + sym::fmaf128 => self.fma_intrinsic::(args, dest)?, + sym::fmuladdf16 => self.float_muladd_intrinsic::(args, dest)?, + sym::fmuladdf32 => self.float_muladd_intrinsic::(args, dest)?, + sym::fmuladdf64 => self.float_muladd_intrinsic::(args, dest)?, + sym::fmuladdf128 => self.float_muladd_intrinsic::(args, dest)?, // Unsupported intrinsic: skip the return_to_block below. _ => return interp_ok(false), @@ -1035,4 +1043,42 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.write_scalar(res, dest)?; interp_ok(()) } + + fn fma_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let c: F = self.read_scalar(&args[2])?.to_float()?; + + let res = a.mul_add(b, c).value; + let res = self.adjust_nan(res, &[a, b, c]); + self.write_scalar(res, dest)?; + interp_ok(()) + } + + fn float_muladd_intrinsic( + &mut self, + args: &[OpTy<'tcx, M::Provenance>], + dest: &PlaceTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, ()> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let a: F = self.read_scalar(&args[0])?.to_float()?; + let b: F = self.read_scalar(&args[1])?.to_float()?; + let c: F = self.read_scalar(&args[2])?.to_float()?; + + let fuse = M::float_fuse_mul_add(self); + + let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value }; + let res = self.adjust_nan(res, &[a, b, c]); + self.write_scalar(res, dest)?; + interp_ok(()) + } } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index e22629993fb..1725635e0b4 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -289,6 +289,9 @@ pub trait Machine<'tcx>: Sized { a } + /// Determines whether the `fmuladd` intrinsics fuse the multiply-add or use separate operations. + fn float_fuse_mul_add(_ecx: &mut InterpCx<'tcx, Self>) -> bool; + /// Called before a basic block terminator is executed. #[inline] fn before_terminator(_ecx: &mut InterpCx<'tcx, Self>) -> InterpResult<'tcx> { @@ -672,6 +675,11 @@ pub macro compile_time_machine(<$tcx: lifetime>) { match fn_val {} } + #[inline(always)] + fn float_fuse_mul_add(_ecx: &mut InterpCx<$tcx, Self>) -> bool { + true + } + #[inline(always)] fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> { // We can't look at `tcx.sess` here as that can differ across crates, which can lead to diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index a174ced5a2a..98eec7303da 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1312,28 +1312,28 @@ pub fn log2f128(x: f128) -> f128; /// [`f16::mul_add`](../../std/primitive.f16.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmaf16(a: f16, b: f16, c: f16) -> f16; +pub const fn fmaf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values. /// /// The stabilized version of this intrinsic is /// [`f32::mul_add`](../../std/primitive.f32.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; +pub const fn fmaf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values. /// /// The stabilized version of this intrinsic is /// [`f64::mul_add`](../../std/primitive.f64.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; +pub const fn fmaf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values. /// /// The stabilized version of this intrinsic is /// [`f128::mul_add`](../../std/primitive.f128.html#method.mul_add) #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; +pub const fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// Returns `a * b + c` for `f16` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the @@ -1347,7 +1347,7 @@ pub fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; +pub const fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// Returns `a * b + c` for `f32` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1360,7 +1360,7 @@ pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; +pub const fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1373,7 +1373,7 @@ pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; +pub const fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// Returns `a * b + c` for `f128` values, non-deterministically executing /// either a fused multiply-add or two operations with rounding of the /// intermediate result. @@ -1386,7 +1386,7 @@ pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64; /// example. #[rustc_intrinsic] #[rustc_nounwind] -pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; +pub const fn fmuladdf128(a: f128, b: f128, c: f128) -> f128; /// Returns the largest integer less than or equal to an `f16`. /// diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 6088fb6fa17..7653db0bf7d 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1659,7 +1659,8 @@ impl f128 { #[doc(alias = "fmaf128", alias = "fusedMultiplyAdd")] #[unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn mul_add(self, a: f128, b: f128) -> f128 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(self, a: f128, b: f128) -> f128 { intrinsics::fmaf128(self, a, b) } diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 3f66c5973d4..58b4dfb4bdf 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1634,7 +1634,8 @@ impl f16 { #[unstable(feature = "f16", issue = "116909")] #[doc(alias = "fmaf16", alias = "fusedMultiplyAdd")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn mul_add(self, a: f16, b: f16) -> f16 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(self, a: f16, b: f16) -> f16 { intrinsics::fmaf16(self, a, b) } diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index ebce89e5b3d..6ff7d24726b 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1799,7 +1799,8 @@ pub mod math { #[doc(alias = "fmaf", alias = "fusedMultiplyAdd")] #[must_use = "method returns a new number and does not mutate the original value"] #[unstable(feature = "core_float_math", issue = "137578")] - pub fn mul_add(x: f32, y: f32, z: f32) -> f32 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(x: f32, y: f32, z: f32) -> f32 { intrinsics::fmaf32(x, y, z) } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 91e3949fc39..f8529a5469b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1797,7 +1797,8 @@ pub mod math { #[doc(alias = "fma", alias = "fusedMultiplyAdd")] #[unstable(feature = "core_float_math", issue = "137578")] #[must_use = "method returns a new number and does not mutate the original value"] - pub fn mul_add(x: f64, a: f64, b: f64) -> f64 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(x: f64, a: f64, b: f64) -> f64 { intrinsics::fmaf64(x, a, b) } diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs index d31eba863f5..62278bf96c3 100644 --- a/library/coretests/tests/floats/f128.rs +++ b/library/coretests/tests/floats/f128.rs @@ -20,24 +20,6 @@ const TOL_PRECISE: f128 = 1e-28; // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support // the intrinsics. -#[test] -#[cfg(not(miri))] -#[cfg(target_has_reliable_f128_math)] -fn test_mul_add() { - let nan: f128 = f128::NAN; - let inf: f128 = f128::INFINITY; - let neg_inf: f128 = f128::NEG_INFINITY; - assert_biteq!(12.3f128.mul_add(4.5, 6.7), 62.0500000000000000000000000000000037); - assert_biteq!((-12.3f128).mul_add(-4.5, -6.7), 48.6500000000000000000000000000000049); - assert_biteq!(0.0f128.mul_add(8.9, 1.2), 1.2); - assert_biteq!(3.4f128.mul_add(-0.0, 5.6), 5.6); - assert!(nan.mul_add(7.8, 9.0).is_nan()); - assert_biteq!(inf.mul_add(7.8, 9.0), inf); - assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf); - assert_biteq!(8.9f128.mul_add(inf, 3.2), inf); - assert_biteq!((-3.2f128).mul_add(2.4, neg_inf), neg_inf); -} - #[test] #[cfg(any(miri, target_has_reliable_f128_math))] fn test_max_recip() { diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs index 302fd0861d7..7ffafd467a5 100644 --- a/library/coretests/tests/floats/f16.rs +++ b/library/coretests/tests/floats/f16.rs @@ -22,24 +22,6 @@ const TOL_P4: f16 = 10.0; // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support // the intrinsics. -#[test] -#[cfg(not(miri))] -#[cfg(target_has_reliable_f16_math)] -fn test_mul_add() { - let nan: f16 = f16::NAN; - let inf: f16 = f16::INFINITY; - let neg_inf: f16 = f16::NEG_INFINITY; - assert_biteq!(12.3f16.mul_add(4.5, 6.7), 62.031); - assert_biteq!((-12.3f16).mul_add(-4.5, -6.7), 48.625); - assert_biteq!(0.0f16.mul_add(8.9, 1.2), 1.2); - assert_biteq!(3.4f16.mul_add(-0.0, 5.6), 5.6); - assert!(nan.mul_add(7.8, 9.0).is_nan()); - assert_biteq!(inf.mul_add(7.8, 9.0), inf); - assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf); - assert_biteq!(8.9f16.mul_add(inf, 3.2), inf); - assert_biteq!((-3.2f16).mul_add(2.4, neg_inf), neg_inf); -} - #[test] #[cfg(any(miri, target_has_reliable_f16_math))] fn test_max_recip() { diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs deleted file mode 100644 index a1fe8b07650..00000000000 --- a/library/coretests/tests/floats/f32.rs +++ /dev/null @@ -1,21 +0,0 @@ -use core::f32; - -use super::assert_biteq; - -// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/ -#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)] -#[test] -fn test_mul_add() { - let nan: f32 = f32::NAN; - let inf: f32 = f32::INFINITY; - let neg_inf: f32 = f32::NEG_INFINITY; - assert_biteq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05); - assert_biteq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65); - assert_biteq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2); - assert_biteq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6); - assert!(f32::math::mul_add(nan, 7.8, 9.0).is_nan()); - assert_biteq!(f32::math::mul_add(inf, 7.8, 9.0), inf); - assert_biteq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf); - assert_biteq!(f32::math::mul_add(8.9f32, inf, 3.2), inf); - assert_biteq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf); -} diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs deleted file mode 100644 index 4c5a3d68d1f..00000000000 --- a/library/coretests/tests/floats/f64.rs +++ /dev/null @@ -1,21 +0,0 @@ -use core::f64; - -use super::assert_biteq; - -// FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/ -#[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)] -#[test] -fn test_mul_add() { - let nan: f64 = f64::NAN; - let inf: f64 = f64::INFINITY; - let neg_inf: f64 = f64::NEG_INFINITY; - assert_biteq!(12.3f64.mul_add(4.5, 6.7), 62.050000000000004); - assert_biteq!((-12.3f64).mul_add(-4.5, -6.7), 48.650000000000006); - assert_biteq!(0.0f64.mul_add(8.9, 1.2), 1.2); - assert_biteq!(3.4f64.mul_add(-0.0, 5.6), 5.6); - assert!(nan.mul_add(7.8, 9.0).is_nan()); - assert_biteq!(inf.mul_add(7.8, 9.0), inf); - assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf); - assert_biteq!(8.9f64.mul_add(inf, 3.2), inf); - assert_biteq!((-3.2f64).mul_add(2.4, neg_inf), neg_inf); -} diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index 31515561c63..9f52adcb6e2 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -34,6 +34,10 @@ trait TestableFloat: Sized { const RAW_12_DOT_5: Self; const RAW_1337: Self; const RAW_MINUS_14_DOT_25: Self; + /// The result of 12.3.mul_add(4.5, 6.7) + const MUL_ADD_RESULT: Self; + /// The result of (-12.3).mul_add(-4.5, -6.7) + const NEG_MUL_ADD_RESULT: Self; } impl TestableFloat for f16 { @@ -58,6 +62,8 @@ impl TestableFloat for f16 { const RAW_12_DOT_5: Self = Self::from_bits(0x4a40); const RAW_1337: Self = Self::from_bits(0x6539); const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xcb20); + const MUL_ADD_RESULT: Self = 62.031; + const NEG_MUL_ADD_RESULT: Self = 48.625; } impl TestableFloat for f32 { @@ -84,6 +90,8 @@ impl TestableFloat for f32 { const RAW_12_DOT_5: Self = Self::from_bits(0x41480000); const RAW_1337: Self = Self::from_bits(0x44a72000); const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc1640000); + const MUL_ADD_RESULT: Self = 62.05; + const NEG_MUL_ADD_RESULT: Self = 48.65; } impl TestableFloat for f64 { @@ -106,6 +114,8 @@ impl TestableFloat for f64 { const RAW_12_DOT_5: Self = Self::from_bits(0x4029000000000000); const RAW_1337: Self = Self::from_bits(0x4094e40000000000); const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc02c800000000000); + const MUL_ADD_RESULT: Self = 62.050000000000004; + const NEG_MUL_ADD_RESULT: Self = 48.650000000000006; } impl TestableFloat for f128 { @@ -128,6 +138,8 @@ impl TestableFloat for f128 { const RAW_12_DOT_5: Self = Self::from_bits(0x40029000000000000000000000000000); const RAW_1337: Self = Self::from_bits(0x40094e40000000000000000000000000); const RAW_MINUS_14_DOT_25: Self = Self::from_bits(0xc002c800000000000000000000000000); + const MUL_ADD_RESULT: Self = 62.0500000000000000000000000000000037; + const NEG_MUL_ADD_RESULT: Self = 48.6500000000000000000000000000000049; } /// Determine the tolerance for values of the argument type. @@ -359,8 +371,6 @@ macro_rules! float_test { mod f128; mod f16; -mod f32; -mod f64; float_test! { name: num, @@ -1542,3 +1552,28 @@ float_test! { assert_biteq!(Float::from_bits(masked_nan2), Float::from_bits(masked_nan2)); } } + +float_test! { + name: mul_add, + attrs: { + f16: #[cfg(any(miri, target_has_reliable_f16))], + // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/ + f32: #[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)], + f64: #[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)], + f128: #[cfg(any(miri, target_has_reliable_f128))], + }, + test { + let nan: Float = Float::NAN; + let inf: Float = Float::INFINITY; + let neg_inf: Float = Float::NEG_INFINITY; + assert_biteq!(flt(12.3).mul_add(4.5, 6.7), Float::MUL_ADD_RESULT); + assert_biteq!((flt(-12.3)).mul_add(-4.5, -6.7), Float::NEG_MUL_ADD_RESULT); + assert_biteq!(flt(0.0).mul_add(8.9, 1.2), 1.2); + assert_biteq!(flt(3.4).mul_add(-0.0, 5.6), 5.6); + assert!(nan.mul_add(7.8, 9.0).is_nan()); + assert_biteq!(inf.mul_add(7.8, 9.0), inf); + assert_biteq!(neg_inf.mul_add(7.8, 9.0), neg_inf); + assert_biteq!(flt(8.9).mul_add(inf, 3.2), inf); + assert_biteq!((flt(-3.2)).mul_add(2.4, neg_inf), neg_inf); + } +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 5c519f3a499..a80d7f8b44d 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(const_convert)] #![feature(const_destruct)] #![feature(const_eval_select)] +#![feature(const_mul_add)] #![feature(const_ops)] #![feature(const_option_ops)] #![feature(const_ref_cell)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 45abd6bca8a..233e41aa345 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -332,6 +332,7 @@ #![feature(char_internals)] #![feature(clone_to_uninit)] #![feature(const_convert)] +#![feature(const_mul_add)] #![feature(core_intrinsics)] #![feature(core_io_borrowed_buf)] #![feature(drop_guard)] diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index ac1d889cc37..e7810e77e76 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -217,7 +217,8 @@ impl f32 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn mul_add(self, a: f32, b: f32) -> f32 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(self, a: f32, b: f32) -> f32 { core::f32::math::mul_add(self, a, b) } diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index 55c8593a0c0..cbebbfb1be1 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -217,7 +217,8 @@ impl f64 { #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] #[inline] - pub fn mul_add(self, a: f64, b: f64) -> f64 { + #[rustc_const_unstable(feature = "const_mul_add", issue = "146724")] + pub const fn mul_add(self, a: f64, b: f64) -> f64 { core::f64::math::mul_add(self, a, b) } diff --git a/src/tools/miri/src/intrinsics/math.rs b/src/tools/miri/src/intrinsics/math.rs index b9c99f28594..0cc4342f0d5 100644 --- a/src/tools/miri/src/intrinsics/math.rs +++ b/src/tools/miri/src/intrinsics/math.rs @@ -1,4 +1,3 @@ -use rand::Rng; use rustc_apfloat::{self, Float, FloatConvert, Round}; use rustc_middle::mir; use rustc_middle::ty::{self, FloatTy}; @@ -39,46 +38,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "sqrtf64" => sqrt::(this, args, dest)?, "sqrtf128" => sqrt::(this, args, dest)?, - "fmaf32" => { - let [a, b, c] = check_intrinsic_arg_count(args)?; - let a = this.read_scalar(a)?.to_f32()?; - let b = this.read_scalar(b)?.to_f32()?; - let c = this.read_scalar(c)?.to_f32()?; - let res = a.mul_add(b, c).value; - let res = this.adjust_nan(res, &[a, b, c]); - this.write_scalar(res, dest)?; - } - "fmaf64" => { - let [a, b, c] = check_intrinsic_arg_count(args)?; - let a = this.read_scalar(a)?.to_f64()?; - let b = this.read_scalar(b)?.to_f64()?; - let c = this.read_scalar(c)?.to_f64()?; - let res = a.mul_add(b, c).value; - let res = this.adjust_nan(res, &[a, b, c]); - this.write_scalar(res, dest)?; - } - - "fmuladdf32" => { - let [a, b, c] = check_intrinsic_arg_count(args)?; - let a = this.read_scalar(a)?.to_f32()?; - let b = this.read_scalar(b)?.to_f32()?; - let c = this.read_scalar(c)?.to_f32()?; - let fuse: bool = this.machine.float_nondet && this.machine.rng.get_mut().random(); - let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value }; - let res = this.adjust_nan(res, &[a, b, c]); - this.write_scalar(res, dest)?; - } - "fmuladdf64" => { - let [a, b, c] = check_intrinsic_arg_count(args)?; - let a = this.read_scalar(a)?.to_f64()?; - let b = this.read_scalar(b)?.to_f64()?; - let c = this.read_scalar(c)?.to_f64()?; - let fuse: bool = this.machine.float_nondet && this.machine.rng.get_mut().random(); - let res = if fuse { a.mul_add(b, c).value } else { ((a * b).value + c).value }; - let res = this.adjust_nan(res, &[a, b, c]); - this.write_scalar(res, dest)?; - } - #[rustfmt::skip] | "fadd_fast" | "fsub_fast" diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 04c8bee72c0..d307636e782 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1293,6 +1293,11 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { ecx.equal_float_min_max(a, b) } + #[inline(always)] + fn float_fuse_mul_add(ecx: &mut InterpCx<'tcx, Self>) -> bool { + ecx.machine.float_nondet && ecx.machine.rng.get_mut().random() + } + #[inline(always)] fn ub_checks(ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool> { interp_ok(ecx.tcx.sess.ub_checks()) -- cgit 1.4.1-3-g733a5 From 92859e98ee1a2101df8322a8581e4d638eb15078 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 24 Sep 2025 20:32:50 +0100 Subject: Repro duration_since regression from issue 146228 --- library/std/src/sys/pal/hermit/time.rs | 11 +++++++++-- library/std/src/sys/pal/unix/time.rs | 27 ++++++++++++--------------- library/std/tests/time.rs | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 17 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f76a5f96c87..bd6fd5a3de4 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -26,15 +26,22 @@ impl Timespec { } fn sub_timespec(&self, other: &Timespec) -> Result { + fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 { + debug_assert!(a >= b); + a.wrapping_sub(b).cast_unsigned() + } + if self >= other { + // Logic here is identical to Unix version of `Timestamp::sub_timespec`, + // check comments there why operations do not overflow. Ok(if self.t.tv_nsec >= other.t.tv_nsec { Duration::new( - (self.t.tv_sec - other.t.tv_sec) as u64, + sub_ge_to_unsigned(self.t.tv_sec, other.t.tv_sec), (self.t.tv_nsec - other.t.tv_nsec) as u32, ) } else { Duration::new( - (self.t.tv_sec - 1 - other.t.tv_sec) as u64, + sub_ge_to_unsigned(self.t.tv_sec - 1, other.t.tv_sec), (self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32, ) }) diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index bd7f74fea6a..c207f41cad4 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -134,28 +134,25 @@ impl Timespec { } pub fn sub_timespec(&self, other: &Timespec) -> Result { + // When a >= b, the difference fits in u64. + fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 { + debug_assert!(a >= b); + a.wrapping_sub(b).cast_unsigned() + } + if self >= other { - // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM - // to optimize it into a branchless form (see also #75545): - // - // 1. `self.tv_sec - other.tv_sec` shows up as a common expression - // in both branches, i.e. the `else` must have its `- 1` - // subtraction after the common one, not interleaved with it - // (it used to be `self.tv_sec - 1 - other.tv_sec`) - // - // 2. the `Duration::new` call (or any other additional complexity) - // is outside of the `if`-`else`, not duplicated in both branches - // - // Ideally this code could be rearranged such that it more - // directly expresses the lower-cost behavior we want from it. let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() { ( - (self.tv_sec - other.tv_sec) as u64, + sub_ge_to_unsigned(self.tv_sec, other.tv_sec), self.tv_nsec.as_inner() - other.tv_nsec.as_inner(), ) } else { + // Following sequence of assertions explain why `self.tv_sec - 1` does not underflow. + debug_assert!(self.tv_nsec < other.tv_nsec); + debug_assert!(self.tv_sec > other.tv_sec); + debug_assert!(self.tv_sec > i64::MIN); ( - (self.tv_sec - other.tv_sec - 1) as u64, + sub_ge_to_unsigned(self.tv_sec - 1, other.tv_sec), self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(), ) }; diff --git a/library/std/tests/time.rs b/library/std/tests/time.rs index 40709eae37c..be1948af915 100644 --- a/library/std/tests/time.rs +++ b/library/std/tests/time.rs @@ -227,3 +227,19 @@ fn big_math() { check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub); check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub); } + +#[test] +#[cfg(unix)] +fn system_time_duration_since_max_range_on_unix() { + // Repro regression https://github.com/rust-lang/rust/issues/146228 + + // Min and max values of `SystemTime` on Unix. + let min = SystemTime::UNIX_EPOCH - (Duration::new(i64::MAX as u64 + 1, 0)); + let max = SystemTime::UNIX_EPOCH + (Duration::new(i64::MAX as u64, 999_999_999)); + + let delta_a = max.duration_since(min).expect("duration_since overflow"); + let delta_b = min.duration_since(max).expect_err("duration_since overflow").duration(); + + assert_eq!(Duration::MAX, delta_a); + assert_eq!(Duration::MAX, delta_b); +} -- cgit 1.4.1-3-g733a5 From 852da23a2d06de5a7821b1fdb356fe3a410b2d00 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Wed, 24 Sep 2025 15:56:38 -0700 Subject: Explicitly note `&[SocketAddr]` impl of `ToSocketAddrs`. Although the examples below this list do imply that there's an impl of `ToSocketAddrs` for `&[SocketAddr]`, it's not actually noted in the list of default implementations. --- library/std/src/net/socket_addr.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'library/std/src') diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs index 5b56dd3f744..8214ad381f1 100644 --- a/library/std/src/net/socket_addr.rs +++ b/library/std/src/net/socket_addr.rs @@ -28,6 +28,8 @@ use crate::{io, iter, option, slice, vec}; /// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like /// `:` pair where `` is a [`u16`] value. /// +/// * &[[SocketAddr]]: all [`SocketAddr`] values in the slice will be used. +/// /// This trait allows constructing network objects like [`TcpStream`] or /// [`UdpSocket`] easily with values of various types for the bind/connection /// address. It is needed because sometimes one type is more appropriate than -- cgit 1.4.1-3-g733a5 From f89660e4aa018401ca993f0df190e5f4c4a6799b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 1 Aug 2025 21:55:11 +0300 Subject: resolve: Do not finalize shadowed bindings I.e. do not mark them as used, or non-speculative loaded, or similar. Previously they were sometimes finalized during early resolution, causing issues like https://github.com/rust-lang/rust/pull/144793#issuecomment-3168108005. --- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 11 ++++++----- library/alloctests/tests/lib.rs | 1 - library/std/src/sys/pal/unix/stack_overflow.rs | 2 +- src/tools/clippy/tests/ui/useless_attribute.fixed | 2 +- src/tools/clippy/tests/ui/useless_attribute.rs | 2 +- .../crates/hir-expand/src/builtin/derive_macro.rs | 2 +- .../crates/hir-expand/src/builtin/fn_macro.rs | 2 +- .../rust-analyzer/crates/hir-expand/src/builtin/quote.rs | 2 -- src/tools/rustfmt/src/config/mod.rs | 1 - tests/ui/resolve/unused-macro-import.rs | 13 +++++++++++++ tests/ui/resolve/unused-macro-import.stderr | 14 ++++++++++++++ 12 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 tests/ui/resolve/unused-macro-import.rs create mode 100644 tests/ui/resolve/unused-macro-import.stderr (limited to 'library/std/src') diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 5821ffa3a30..5d32950875a 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -5,7 +5,7 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ AttrStyle, Attribute, Block, Error, Expr, Ident, Pat, ReturnType, Token, Type, braced, - parenthesized, parse_macro_input, parse_quote, token, + parenthesized, parse_macro_input, token, }; mod kw { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 35051675fd8..51489019950 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -492,14 +492,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => Err(Determinacy::Determined), }, Scope::Module(module, derive_fallback_lint_id) => { - // FIXME: use `finalize_scope` here. let (adjusted_parent_scope, adjusted_finalize) = if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) { - (parent_scope, finalize) + (parent_scope, finalize_scope!()) } else { ( &ParentScope { module, ..*parent_scope }, - finalize.map(|f| Finalize { used: Used::Scope, ..f }), + finalize_scope!().map(|f| Finalize { used: Used::Scope, ..f }), ) }; let binding = this.reborrow().resolve_ident_in_module_unadjusted( @@ -557,8 +556,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => Err(Determinacy::Determined), }, Scope::ExternPreludeItems => { - // FIXME: use `finalize_scope` here. - match this.reborrow().extern_prelude_get_item(ident, finalize.is_some()) { + match this + .reborrow() + .extern_prelude_get_item(ident, finalize_scope!().is_some()) + { Some(binding) => { extern_prelude_item_binding = Some(binding); Ok((binding, Flags::empty())) diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 8c3ce156f3c..4947b38ba89 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -46,7 +46,6 @@ #![deny(unsafe_op_in_unsafe_fn)] extern crate alloc; -extern crate test; use std::hash::{DefaultHasher, Hash, Hasher}; diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0d2100d66bc..51463eef5b7 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -72,7 +72,7 @@ mod imp { use crate::sync::OnceLock; use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; use crate::sys::pal::unix::os; - use crate::{io, mem, panic, ptr}; + use crate::{io, mem, ptr}; // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages // (unmapped pages) at the end of every thread's stack, so if a thread ends diff --git a/src/tools/clippy/tests/ui/useless_attribute.fixed b/src/tools/clippy/tests/ui/useless_attribute.fixed index 15070dd9c2c..e0bc23e0788 100644 --- a/src/tools/clippy/tests/ui/useless_attribute.fixed +++ b/src/tools/clippy/tests/ui/useless_attribute.fixed @@ -153,7 +153,7 @@ pub mod redundant_imports_issue { () => {}; } - #[expect(redundant_imports)] + #[expect(unused_imports)] pub(crate) use empty; empty!(); diff --git a/src/tools/clippy/tests/ui/useless_attribute.rs b/src/tools/clippy/tests/ui/useless_attribute.rs index 3f530de7fd8..30a4c354b23 100644 --- a/src/tools/clippy/tests/ui/useless_attribute.rs +++ b/src/tools/clippy/tests/ui/useless_attribute.rs @@ -153,7 +153,7 @@ pub mod redundant_imports_issue { () => {}; } - #[expect(redundant_imports)] + #[expect(unused_imports)] pub(crate) use empty; empty!(); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index 15e68ff95cd..0fa412ad7fa 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -12,7 +12,7 @@ use tracing::debug; use crate::{ ExpandError, ExpandResult, MacroCallId, - builtin::quote::{dollar_crate, quote}, + builtin::quote::dollar_crate, db::ExpandDatabase, hygiene::span_with_def_site_ctxt, name::{self, AsName, Name}, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index ec344613761..6fe63f249cd 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -19,7 +19,7 @@ use syntax_bridge::syntax_node_to_token_tree; use crate::{ EditionedFileId, ExpandError, ExpandResult, Lookup as _, MacroCallId, - builtin::quote::{WithDelimiter, dollar_crate, quote}, + builtin::quote::{WithDelimiter, dollar_crate}, db::ExpandDatabase, hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt}, name, diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 70c38d4d7c7..84dd4a24d90 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -229,8 +229,6 @@ mod tests { use span::{Edition, ROOT_ERASED_FILE_AST_ID, SpanAnchor, SyntaxContext}; use syntax::{TextRange, TextSize}; - use super::quote; - const DUMMY: tt::Span = tt::Span { range: TextRange::empty(TextSize::new(0)), anchor: SpanAnchor { diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 6b63108c037..525953bf445 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -516,7 +516,6 @@ mod test { #[allow(dead_code)] mod mock { use super::super::*; - use crate::config_option_with_style_edition_default; use rustfmt_config_proc_macro::config_type; #[config_type] diff --git a/tests/ui/resolve/unused-macro-import.rs b/tests/ui/resolve/unused-macro-import.rs new file mode 100644 index 00000000000..e85f7a43993 --- /dev/null +++ b/tests/ui/resolve/unused-macro-import.rs @@ -0,0 +1,13 @@ +//@ check-pass + +#![warn(unused_imports)] + +#[macro_export] +macro_rules! mac { () => {} } + +fn main() { + // Unused, `mac` as `macro_rules!` is already in scope and has higher priority. + use crate::mac; //~ WARN unused import: `crate::mac` + + mac!(); +} diff --git a/tests/ui/resolve/unused-macro-import.stderr b/tests/ui/resolve/unused-macro-import.stderr new file mode 100644 index 00000000000..5f9813808a0 --- /dev/null +++ b/tests/ui/resolve/unused-macro-import.stderr @@ -0,0 +1,14 @@ +warning: unused import: `crate::mac` + --> $DIR/unused-macro-import.rs:10:9 + | +LL | use crate::mac; + | ^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-macro-import.rs:3:9 + | +LL | #![warn(unused_imports)] + | ^^^^^^^^^^^^^^ + +warning: 1 warning emitted + -- cgit 1.4.1-3-g733a5 From 0ede3fe48c0d373d3673459218e1b9e7eaa667b8 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Thu, 25 Sep 2025 16:34:20 -0500 Subject: std: fix warning in VEXos stdio module --- library/std/src/sys/stdio/vexos.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/stdio/vexos.rs b/library/std/src/sys/stdio/vexos.rs index 1f2251c6421..9a391feb7a8 100644 --- a/library/std/src/sys/stdio/vexos.rs +++ b/library/std/src/sys/stdio/vexos.rs @@ -13,7 +13,7 @@ impl Stdin { } impl io::Read for Stdin { - fn read(&mut self, mut buf: &mut [u8]) -> io::Result { + fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut count = 0; for out_byte in buf.iter_mut() { -- cgit 1.4.1-3-g733a5 From c0de794949f652b368fa107c3b52d0515f1f3859 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Apr 2025 19:01:08 +0100 Subject: std::net: update tcp deferaccept delay type to Duration. --- library/std/src/os/net/linux_ext/tcp.rs | 23 ++++++++++++++--------- library/std/src/os/net/linux_ext/tests.rs | 11 +++++++---- library/std/src/sys/net/connection/socket/unix.rs | 9 +++++---- 3 files changed, 26 insertions(+), 17 deletions(-) (limited to 'library/std/src') diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index fde53ec4257..dbefc91a979 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -4,6 +4,7 @@ use crate::sealed::Sealed; use crate::sys_common::AsInner; +use crate::time::Duration; use crate::{io, net}; /// Os-specific extensions for [`TcpStream`] @@ -59,11 +60,13 @@ pub trait TcpStreamExt: Sealed { /// A socket listener will be awakened solely when data arrives. /// - /// The `accept` argument set the delay in seconds until the + /// The `accept` argument set the maximum delay until the /// data is available to read, reducing the number of short lived /// connections without data to process. /// Contrary to other platforms `SO_ACCEPTFILTER` feature equivalent, there is /// no necessity to set it after the `listen` call. + /// Note that the delay is expressed as Duration from user's perspective + /// the call rounds it down to the nearest second expressible as a `c_int`. /// /// See [`man 7 tcp`](https://man7.org/linux/man-pages/man7/tcp.7.html) /// @@ -73,16 +76,17 @@ pub trait TcpStreamExt: Sealed { /// #![feature(tcp_deferaccept)] /// use std::net::TcpStream; /// use std::os::linux::net::TcpStreamExt; + /// use std::time::Duration; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); - /// stream.set_deferaccept(1).expect("set_deferaccept call failed"); + /// stream.set_deferaccept(Duration::from_secs(1u64)).expect("set_deferaccept call failed"); /// ``` #[unstable(feature = "tcp_deferaccept", issue = "119639")] #[cfg(target_os = "linux")] - fn set_deferaccept(&self, accept: u32) -> io::Result<()>; + fn set_deferaccept(&self, accept: Duration) -> io::Result<()>; - /// Gets the accept delay value (in seconds) of the `TCP_DEFER_ACCEPT` option. + /// Gets the accept delay value of the `TCP_DEFER_ACCEPT` option. /// /// For more information about this option, see [`TcpStreamExt::set_deferaccept`]. /// @@ -92,15 +96,16 @@ pub trait TcpStreamExt: Sealed { /// #![feature(tcp_deferaccept)] /// use std::net::TcpStream; /// use std::os::linux::net::TcpStreamExt; + /// use std::time::Duration; /// /// let stream = TcpStream::connect("127.0.0.1:8080") /// .expect("Couldn't connect to the server..."); - /// stream.set_deferaccept(1).expect("set_deferaccept call failed"); - /// assert_eq!(stream.deferaccept().unwrap_or(0), 1); + /// stream.set_deferaccept(Duration::from_secs(1u64)).expect("set_deferaccept call failed"); + /// assert_eq!(stream.deferaccept().unwrap(), Duration::from_secs(1u64)); /// ``` #[unstable(feature = "tcp_deferaccept", issue = "119639")] #[cfg(target_os = "linux")] - fn deferaccept(&self) -> io::Result; + fn deferaccept(&self) -> io::Result; } #[stable(feature = "tcp_quickack", since = "1.89.0")] @@ -117,12 +122,12 @@ impl TcpStreamExt for net::TcpStream { } #[cfg(target_os = "linux")] - fn set_deferaccept(&self, accept: u32) -> io::Result<()> { + fn set_deferaccept(&self, accept: Duration) -> io::Result<()> { self.as_inner().as_inner().set_deferaccept(accept) } #[cfg(target_os = "linux")] - fn deferaccept(&self) -> io::Result { + fn deferaccept(&self) -> io::Result { self.as_inner().as_inner().deferaccept() } } diff --git a/library/std/src/os/net/linux_ext/tests.rs b/library/std/src/os/net/linux_ext/tests.rs index 12f35696abc..0758b426ccc 100644 --- a/library/std/src/os/net/linux_ext/tests.rs +++ b/library/std/src/os/net/linux_ext/tests.rs @@ -32,6 +32,7 @@ fn deferaccept() { use crate::net::test::next_test_ip4; use crate::net::{TcpListener, TcpStream}; use crate::os::net::linux_ext::tcp::TcpStreamExt; + use crate::time::Duration; macro_rules! t { ($e:expr) => { @@ -43,10 +44,12 @@ fn deferaccept() { } let addr = next_test_ip4(); + let one = Duration::from_secs(1u64); + let zero = Duration::from_secs(0u64); let _listener = t!(TcpListener::bind(&addr)); let stream = t!(TcpStream::connect(&("localhost", addr.port()))); - stream.set_deferaccept(1).expect("set_deferaccept failed"); - assert_eq!(stream.deferaccept().unwrap(), 1); - stream.set_deferaccept(0).expect("set_deferaccept failed"); - assert_eq!(stream.deferaccept().unwrap(), 0); + stream.set_deferaccept(one).expect("set_deferaccept failed"); + assert_eq!(stream.deferaccept().unwrap(), one); + stream.set_deferaccept(zero).expect("set_deferaccept failed"); + assert_eq!(stream.deferaccept().unwrap(), zero); } diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index 8b5970d1494..86b966242bf 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -485,14 +485,15 @@ impl Socket { // bionic libc makes no use of this flag #[cfg(target_os = "linux")] - pub fn set_deferaccept(&self, accept: u32) -> io::Result<()> { - setsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT, accept as c_int) + pub fn set_deferaccept(&self, accept: Duration) -> io::Result<()> { + let val = cmp::min(accept.as_secs(), c_int::MAX as u64) as c_int; + setsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT, val) } #[cfg(target_os = "linux")] - pub fn deferaccept(&self) -> io::Result { + pub fn deferaccept(&self) -> io::Result { let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_DEFER_ACCEPT)?; - Ok(raw as u32) + Ok(Duration::from_secs(raw as _)) } #[cfg(any(target_os = "freebsd", target_os = "netbsd"))] -- cgit 1.4.1-3-g733a5 From 4e9716fbc5fb0f85d838ee9350ade2be5c2a6201 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 14 Sep 2025 10:30:29 -0400 Subject: Update CURRENT_RUSTC_VERSION post-bump --- compiler/rustc_feature/src/accepted.rs | 6 +- compiler/rustc_feature/src/removed.rs | 4 +- compiler/rustc_feature/src/unstable.rs | 18 +++--- library/alloc/src/boxed.rs | 2 +- library/alloc/src/collections/btree/map.rs | 10 ++-- library/alloc/src/collections/btree/set.rs | 10 ++-- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- library/core/src/any.rs | 2 +- library/core/src/array/mod.rs | 6 +- library/core/src/cell.rs | 4 +- library/core/src/iter/adapters/chain.rs | 2 +- library/core/src/iter/adapters/mod.rs | 2 +- library/core/src/iter/mod.rs | 2 +- library/core/src/iter/traits/accum.rs | 2 +- library/core/src/net/ip_addr.rs | 12 ++-- library/core/src/num/int_macros.rs | 56 +++++++++---------- library/core/src/num/uint_macros.rs | 64 +++++++++++----------- library/core/src/ptr/mod.rs | 4 +- library/core/src/str/mod.rs | 8 +-- library/core/src/sync/atomic.rs | 14 ++--- library/core/src/time.rs | 8 +-- library/std/src/ffi/os_str.rs | 2 +- library/std/src/os/windows/ffi.rs | 2 +- library/std/src/panic.rs | 2 +- library/std/src/path.rs | 24 ++++---- .../rustc/src/platform-support/apple-ios-macabi.md | 2 +- src/doc/rustc/src/platform-support/apple-ios.md | 2 +- .../ui/feature-gates/feature-gate-sanitize.stderr | 2 +- 29 files changed, 138 insertions(+), 138 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 6af4cfb0e56..364a1202b05 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -205,7 +205,7 @@ declare_features! ( (accepted, extended_key_value_attributes, "1.54.0", Some(78835)), /// Allows using `aapcs`, `efiapi`, `sysv64` and `win64` as calling conventions /// for functions with varargs. - (accepted, extended_varargs_abi_support, "CURRENT_RUSTC_VERSION", Some(100189)), + (accepted, extended_varargs_abi_support, "1.91.0", Some(100189)), /// Allows resolving absolute paths as paths from other crates. (accepted, extern_absolute_paths, "1.30.0", Some(44660)), /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude. @@ -400,7 +400,7 @@ declare_features! ( /// Allows use of `&foo[a..b]` as a slicing syntax. (accepted, slicing_syntax, "1.0.0", None), /// Allows use of `sse4a` target feature. - (accepted, sse4a_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (accepted, sse4a_target_feature, "1.91.0", Some(44839)), /// Allows elision of `'static` lifetimes in `static`s and `const`s. (accepted, static_in_const, "1.17.0", Some(35897)), /// Allows the definition recursive static items. @@ -414,7 +414,7 @@ declare_features! ( /// Allows the use of `#[target_feature]` on safe functions. (accepted, target_feature_11, "1.86.0", Some(69098)), /// Allows use of `tbm` target feature. - (accepted, tbm_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (accepted, tbm_target_feature, "1.91.0", Some(44839)), /// Allows `fn main()` with return types which implements `Termination` (RFC 1937). (accepted, termination_trait, "1.26.0", Some(43301)), /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937). diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index e37fc6b7bfc..32115535e99 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -192,7 +192,7 @@ declare_features! ( (removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667), // Allows the use of `no_sanitize` attribute. /// The feature was renamed to `sanitize` and the attribute to `#[sanitize(xyz = "on|off")]` - (removed, no_sanitize, "CURRENT_RUSTC_VERSION", Some(39699), Some(r#"renamed to sanitize(xyz = "on|off")"#), 142681), + (removed, no_sanitize, "1.91.0", Some(39699), Some(r#"renamed to sanitize(xyz = "on|off")"#), 142681), /// Note: this feature was previously recorded in a separate /// `STABLE_REMOVED` list because it, uniquely, was once stable but was /// then removed. But there was no utility storing it separately, so now @@ -203,7 +203,7 @@ declare_features! ( (removed, object_safe_for_dispatch, "1.83.0", Some(43561), Some("renamed to `dyn_compatible_for_dispatch`"), 131511), /// Allows using `#[omit_gdb_pretty_printer_section]`. - (removed, omit_gdb_pretty_printer_section, "CURRENT_RUSTC_VERSION", None, None, 144738), + (removed, omit_gdb_pretty_printer_section, "1.91.0", None, None, 144738), /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None, 65794), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 93e5588146e..6ef0df72365 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -327,7 +327,7 @@ declare_features! ( (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), (unstable, movrs_target_feature, "1.88.0", Some(137976)), - (unstable, nvptx_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), + (unstable, nvptx_target_feature, "1.91.0", Some(44839)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), @@ -471,7 +471,7 @@ declare_features! ( /// Allows deref patterns. (incomplete, deref_patterns, "1.79.0", Some(87121)), /// Allows deriving the From trait on single-field structs. - (unstable, derive_from, "CURRENT_RUSTC_VERSION", Some(144889)), + (unstable, derive_from, "1.91.0", Some(144889)), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (unstable, doc_auto_cfg, "1.58.0", Some(43781)), /// Allows `#[doc(cfg(...))]`. @@ -481,7 +481,7 @@ declare_features! ( /// Allows `#[doc(masked)]`. (unstable, doc_masked, "1.21.0", Some(44027)), /// Allows features to allow target_feature to better interact with traits. - (incomplete, effective_target_features, "CURRENT_RUSTC_VERSION", Some(143352)), + (incomplete, effective_target_features, "1.91.0", Some(143352)), /// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }` (incomplete, ergonomic_clones, "1.87.0", Some(132290)), /// Allows exhaustive pattern matching on types that contain uninhabited types. @@ -554,9 +554,9 @@ declare_features! ( /// Allows fused `loop`/`match` for direct intraprocedural jumps. (incomplete, loop_match, "1.90.0", Some(132306)), /// Allow `macro_rules!` attribute rules - (unstable, macro_attr, "CURRENT_RUSTC_VERSION", Some(83527)), + (unstable, macro_attr, "1.91.0", Some(83527)), /// Allow `macro_rules!` derive rules - (unstable, macro_derive, "CURRENT_RUSTC_VERSION", Some(143549)), + (unstable, macro_derive, "1.91.0", Some(143549)), /// Give access to additional metadata about declarative macro meta-variables. (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. @@ -613,7 +613,7 @@ declare_features! ( (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), /// Allows the use of raw-dylibs on ELF platforms (incomplete, raw_dylib_elf, "1.87.0", Some(135694)), - (unstable, reborrow, "CURRENT_RUSTC_VERSION", Some(145612)), + (unstable, reborrow, "1.91.0", Some(145612)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant @@ -627,13 +627,13 @@ declare_features! ( /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), /// Allows the use of the `sanitize` attribute. - (unstable, sanitize, "CURRENT_RUSTC_VERSION", Some(39699)), + (unstable, sanitize, "1.91.0", Some(39699)), /// Allows the use of SIMD types in functions declared in `extern` blocks. (unstable, simd_ffi, "1.0.0", Some(27731)), /// Allows specialization of implementations (RFC 1210). (incomplete, specialization, "1.7.0", Some(31844)), /// Allows using `#[rustc_align_static(...)]` on static items. - (unstable, static_align, "CURRENT_RUSTC_VERSION", Some(146177)), + (unstable, static_align, "1.91.0", Some(146177)), /// Allows attributes on expressions and non-item statements. (unstable, stmt_expr_attributes, "1.6.0", Some(15701)), /// Allows lints part of the strict provenance effort. @@ -645,7 +645,7 @@ declare_features! ( /// Allows subtrait items to shadow supertrait items. (unstable, supertrait_item_shadowing, "1.86.0", Some(89151)), /// Allows the use of target_feature when a function is marked inline(always). - (unstable, target_feature_inline_always, "CURRENT_RUSTC_VERSION", Some(145574)), + (unstable, target_feature_inline_always, "1.91.0", Some(145574)), /// Allows using `#[thread_local]` on `static` items. (unstable, thread_local, "1.0.0", Some(29594)), /// Allows defining `trait X = A + B;` alias items. diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 1c549f7b6ba..5a63d90b95f 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1706,7 +1706,7 @@ impl Default for Box { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "pin_default_impls", since = "1.91.0")] impl Default for Pin> where T: ?Sized, diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e3b53b2fe29..9dfbbd91322 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -1456,7 +1456,7 @@ impl BTreeMap { /// assert_eq!(low.keys().copied().collect::>(), [0, 1, 2, 3]); /// assert_eq!(high.keys().copied().collect::>(), [4, 5, 6, 7]); /// ``` - #[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "btree_extract_if", since = "1.91.0")] pub fn extract_if(&mut self, range: R, pred: F) -> ExtractIf<'_, K, V, R, F, A> where K: Ord, @@ -1943,7 +1943,7 @@ impl Default for Values<'_, K, V> { } /// An iterator produced by calling `extract_if` on BTreeMap. -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf< 'a, @@ -1976,7 +1976,7 @@ pub(super) struct ExtractIfInner<'a, K, V, R> { range: R, } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl fmt::Debug for ExtractIf<'_, K, V, R, F, A> where K: fmt::Debug, @@ -1988,7 +1988,7 @@ where } } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl Iterator for ExtractIf<'_, K, V, R, F, A> where K: PartialOrd, @@ -2062,7 +2062,7 @@ impl<'a, K, V, R> ExtractIfInner<'a, K, V, R> { } } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl FusedIterator for ExtractIf<'_, K, V, R, F> where K: PartialOrd, diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index e6b0a1f6323..6e6996bcbd6 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1218,7 +1218,7 @@ impl BTreeSet { /// assert_eq!(low.into_iter().collect::>(), [0, 1, 2, 3]); /// assert_eq!(high.into_iter().collect::>(), [4, 5, 6, 7]); /// ``` - #[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "btree_extract_if", since = "1.91.0")] pub fn extract_if(&mut self, range: R, pred: F) -> ExtractIf<'_, T, R, F, A> where T: Ord, @@ -1553,7 +1553,7 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet { } /// An iterator produced by calling `extract_if` on BTreeSet. -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ExtractIf< 'a, @@ -1568,7 +1568,7 @@ pub struct ExtractIf< alloc: A, } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl fmt::Debug for ExtractIf<'_, T, R, F, A> where T: fmt::Debug, @@ -1581,7 +1581,7 @@ where } } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl Iterator for ExtractIf<'_, T, R, F, A> where T: PartialOrd, @@ -1601,7 +1601,7 @@ where } } -#[stable(feature = "btree_extract_if", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "btree_extract_if", since = "1.91.0")] impl FusedIterator for ExtractIf<'_, T, R, F, A> where T: PartialOrd, diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index aed3357afbf..627e5c7f976 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2377,7 +2377,7 @@ impl Default for Rc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "pin_default_impls", since = "1.91.0")] impl Default for Pin> where T: ?Sized, diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a466b74944c..3a8695d34a8 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3636,7 +3636,7 @@ impl Default for Arc<[T]> { } #[cfg(not(no_global_oom_handling))] -#[stable(feature = "pin_default_impls", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "pin_default_impls", since = "1.91.0")] impl Default for Pin> where T: ?Sized, diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 76ea2d18a82..3ab95438c3f 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -774,7 +774,7 @@ impl TypeId { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_type_id", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_type_id", since = "1.91.0")] pub const fn of() -> TypeId { const { intrinsics::type_id::() } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index d713e575b58..0dc10758a85 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -49,7 +49,7 @@ pub use iter::IntoIter; /// ``` #[inline] #[must_use = "cloning is often expensive and is not expected to have side effects"] -#[stable(feature = "array_repeat", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "array_repeat", since = "1.91.0")] pub fn repeat(val: T) -> [T; N] { from_trusted_iterator(repeat_n(val, N)) } @@ -627,7 +627,7 @@ impl [T; N] { /// assert_eq!(strings.len(), 3); /// ``` #[stable(feature = "array_methods", since = "1.77.0")] - #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_array_each_ref", since = "1.91.0")] pub const fn each_ref(&self) -> [&T; N] { let mut buf = [null::(); N]; @@ -658,7 +658,7 @@ impl [T; N] { /// assert_eq!(floats, [0.0, 2.7, -1.0]); /// ``` #[stable(feature = "array_methods", since = "1.77.0")] - #[rustc_const_stable(feature = "const_array_each_ref", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_array_each_ref", since = "1.91.0")] pub const fn each_mut(&mut self) -> [&mut T; N] { let mut buf = [null_mut::(); N]; diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7d4a66640b1..6aadb7a86cd 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -705,8 +705,8 @@ impl Cell<[T; N]> { /// let cell_array: &Cell<[i32; 3]> = Cell::from_mut(&mut array); /// let array_cell: &[Cell; 3] = cell_array.as_array_of_cells(); /// ``` - #[stable(feature = "as_array_of_cells", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "as_array_of_cells", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "as_array_of_cells", since = "1.91.0")] + #[rustc_const_stable(feature = "as_array_of_cells", since = "1.91.0")] pub const fn as_array_of_cells(&self) -> &[Cell; N] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T; N]> as *const [Cell; N]) } diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index 3ebdf7b4727..0ece54554d4 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -60,7 +60,7 @@ impl Chain { /// assert_eq!(iter.next(), Some(6)); /// assert_eq!(iter.next(), None); /// ``` -#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_chain", since = "1.91.0")] pub fn chain(a: A, b: B) -> Chain where A: IntoIterator, diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index 6c6de0a4e5c..1ff5093922b 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -32,7 +32,7 @@ mod zip; pub use self::array_chunks::ArrayChunks; #[unstable(feature = "std_internals", issue = "none")] pub use self::by_ref_sized::ByRefSized; -#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_chain", since = "1.91.0")] pub use self::chain::chain; #[stable(feature = "iter_cloned", since = "1.1.0")] pub use self::cloned::Cloned; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index bc07324f520..c7e1c4ef767 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -404,7 +404,7 @@ pub use self::adapters::StepBy; pub use self::adapters::TrustedRandomAccess; #[unstable(feature = "trusted_random_access", issue = "none")] pub use self::adapters::TrustedRandomAccessNoCoerce; -#[stable(feature = "iter_chain", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "iter_chain", since = "1.91.0")] pub use self::adapters::chain; pub(crate) use self::adapters::try_process; #[stable(feature = "iter_zip", since = "1.59.0")] diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index 3b805139ded..375b5ef5285 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -148,7 +148,7 @@ macro_rules! saturating_integer_sum_product { saturating_integer_sum_product!(@impls Saturating(0), Saturating(1), "The short-circuiting behavior of this implementation is unspecified. If you care about \ short-circuiting, use [`Iterator::fold`] directly.", - #[stable(feature = "saturating_iter_arith", since = "CURRENT_RUSTC_VERSION")], + #[stable(feature = "saturating_iter_arith", since = "1.91.0")], $(Saturating<$a>)*); ); } diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 9779fb8fe4d..a1bfd774710 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -631,8 +631,8 @@ impl Ipv4Addr { /// let addr = Ipv4Addr::from_octets([13u8, 12u8, 11u8, 10u8]); /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr); /// ``` - #[stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_from", since = "1.91.0")] + #[rustc_const_stable(feature = "ip_from", since = "1.91.0")] #[must_use] #[inline] pub const fn from_octets(octets: [u8; 4]) -> Ipv4Addr { @@ -1478,8 +1478,8 @@ impl Ipv6Addr { /// addr /// ); /// ``` - #[stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_from", since = "1.91.0")] + #[rustc_const_stable(feature = "ip_from", since = "1.91.0")] #[must_use] #[inline] pub const fn from_segments(segments: [u16; 8]) -> Ipv6Addr { @@ -2043,8 +2043,8 @@ impl Ipv6Addr { /// addr /// ); /// ``` - #[stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "ip_from", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "ip_from", since = "1.91.0")] + #[rustc_const_stable(feature = "ip_from", since = "1.91.0")] #[must_use] #[inline] pub const fn from_octets(octets: [u8; 16]) -> Ipv6Addr { diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 0d80c40fb23..c3460a64090 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -519,8 +519,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -609,8 +609,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -659,8 +659,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -749,8 +749,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -799,8 +799,8 @@ macro_rules! int_impl { /// ``` should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -906,8 +906,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -973,8 +973,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1139,8 +1139,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1205,8 +1205,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1286,8 +1286,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1342,8 +1342,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1517,8 +1517,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1693,8 +1693,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1762,8 +1762,8 @@ macro_rules! int_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d68c7be9865..752498bfbd8 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -667,8 +667,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -762,8 +762,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -821,8 +821,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -946,8 +946,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1002,8 +1002,8 @@ macro_rules! uint_impl { "::MAX), Some(0));" )] /// ``` - #[stable(feature = "unsigned_signed_diff", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsigned_signed_diff", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_signed_diff", since = "1.91.0")] + #[rustc_const_stable(feature = "unsigned_signed_diff", since = "1.91.0")] #[inline] pub const fn checked_signed_diff(self, rhs: Self) -> Option<$SignedT> { let res = self.wrapping_sub(rhs) as $SignedT; @@ -1055,8 +1055,8 @@ macro_rules! uint_impl { /// ``` should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1151,8 +1151,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1205,8 +1205,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1353,8 +1353,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1409,8 +1409,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1694,8 +1694,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1750,8 +1750,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1922,8 +1922,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2104,8 +2104,8 @@ macro_rules! uint_impl { /// ```should_panic #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_overflow_ops", since = "1.91.0")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "1.91.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -2682,7 +2682,7 @@ macro_rules! uint_impl { /// /// assert_eq!((sum1, sum0), (9, 6)); /// ``` - #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2774,7 +2774,7 @@ macro_rules! uint_impl { /// #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")] /// ``` - #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -2991,7 +2991,7 @@ macro_rules! uint_impl { /// 789_u16.wrapping_mul(456).wrapping_add(123), /// ); /// ``` - #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] @@ -3057,7 +3057,7 @@ macro_rules! uint_impl { /// u32::to_le_bytes(0xcffc982d) /// ); /// ``` - #[stable(feature = "unsigned_bigint_helpers", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsigned_bigint_helpers", since = "1.91.0")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ without modifying the original"] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 625024373ef..b29d2676542 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -975,7 +975,7 @@ pub const fn dangling_mut() -> *mut T { #[must_use] #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] -#[rustc_const_stable(feature = "const_exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_exposed_provenance", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub const fn with_exposed_provenance(addr: usize) -> *const T { @@ -1016,7 +1016,7 @@ pub const fn with_exposed_provenance(addr: usize) -> *const T { #[must_use] #[inline(always)] #[stable(feature = "exposed_provenance", since = "1.84.0")] -#[rustc_const_stable(feature = "const_exposed_provenance", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "const_exposed_provenance", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[allow(fuzzy_provenance_casts)] // this *is* the explicit provenance API one should use instead pub const fn with_exposed_provenance_mut(addr: usize) -> *mut T { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 2e473d348b0..3a5efa7d835 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -404,8 +404,8 @@ impl str { /// assert_eq!(closest, 10); /// assert_eq!(&s[..closest], "❤️🧡"); /// ``` - #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_char_boundary", since = "1.91.0")] + #[rustc_const_stable(feature = "round_char_boundary", since = "1.91.0")] #[inline] pub const fn floor_char_boundary(&self, index: usize) -> usize { if index >= self.len() { @@ -447,8 +447,8 @@ impl str { /// assert_eq!(closest, 14); /// assert_eq!(&s[..closest], "❤️🧡💛"); /// ``` - #[stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "round_char_boundary", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_char_boundary", since = "1.91.0")] + #[rustc_const_stable(feature = "round_char_boundary", since = "1.91.0")] #[inline] pub const fn ceil_char_boundary(&self, index: usize) -> usize { if index >= self.len() { diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 1b4a54b1b7a..30a42d4eb5e 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -2208,7 +2208,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_add(val.wrapping_mul(size_of::()), order) @@ -2252,7 +2252,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T { self.fetch_byte_sub(val.wrapping_mul(size_of::()), order) @@ -2286,7 +2286,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2321,7 +2321,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2371,7 +2371,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2420,7 +2420,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. @@ -2467,7 +2467,7 @@ impl AtomicPtr { /// ``` #[inline] #[cfg(target_has_atomic = "ptr")] - #[stable(feature = "strict_provenance_atomic_ptr", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "strict_provenance_atomic_ptr", since = "1.91.0")] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T { // SAFETY: data races are prevented by atomic intrinsics. diff --git a/library/core/src/time.rs b/library/core/src/time.rs index d205bc376f1..f721fcd6156 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -416,8 +416,8 @@ impl Duration { /// assert_eq!(6 * 60 * 60, duration.as_secs()); /// assert_eq!(0, duration.subsec_nanos()); /// ``` - #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "duration_constructors_lite", since = "1.91.0")] + #[rustc_const_stable(feature = "duration_constructors_lite", since = "1.91.0")] #[must_use] #[inline] pub const fn from_hours(hours: u64) -> Duration { @@ -444,8 +444,8 @@ impl Duration { /// assert_eq!(10 * 60, duration.as_secs()); /// assert_eq!(0, duration.subsec_nanos()); /// ``` - #[stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "duration_constructors_lite", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "duration_constructors_lite", since = "1.91.0")] + #[rustc_const_stable(feature = "duration_constructors_lite", since = "1.91.0")] #[must_use] #[inline] pub const fn from_mins(mins: u64) -> Duration { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index a39565d2159..6c098034eea 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -137,7 +137,7 @@ impl OsString { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")] pub const fn new() -> OsString { OsString { inner: Buf::from_string(String::new()) } } diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index 345d5b74285..20e5383dc09 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -141,7 +141,7 @@ impl OsStrExt for OsStr { pub struct EncodeWide<'a> { inner: alloc::wtf8::EncodeWide<'a>, } -#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "encode_wide_debug", since = "1.91.0")] impl fmt::Debug for EncodeWide<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.inner, f) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 5e8d2f8e78e..1997785885d 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -122,7 +122,7 @@ impl<'a> PanicHookInfo<'a> { /// ``` #[must_use] #[inline] - #[stable(feature = "panic_payload_as_str", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "panic_payload_as_str", since = "1.91.0")] pub fn payload_as_str(&self) -> Option<&str> { if let Some(s) = self.payload.downcast_ref::<&str>() { Some(s) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 88d8a4f21ca..718c7c2e3b1 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1191,7 +1191,7 @@ impl PathBuf { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] #[inline] - #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")] pub const fn new() -> PathBuf { PathBuf { inner: OsString::new() } } @@ -1594,7 +1594,7 @@ impl PathBuf { /// p.add_extension(""); /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path()); /// ``` - #[stable(feature = "path_add_extension", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "path_add_extension", since = "1.91.0")] pub fn add_extension>(&mut self, extension: S) -> bool { self._add_extension(extension.as_ref()) } @@ -2103,7 +2103,7 @@ impl PartialEq for PathBuf { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for PathBuf { #[inline] fn eq(&self, other: &str) -> bool { @@ -2111,7 +2111,7 @@ impl cmp::PartialEq for PathBuf { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for str { #[inline] fn eq(&self, other: &PathBuf) -> bool { @@ -2119,7 +2119,7 @@ impl cmp::PartialEq for str { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for PathBuf { #[inline] fn eq(&self, other: &String) -> bool { @@ -2127,7 +2127,7 @@ impl cmp::PartialEq for PathBuf { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for String { #[inline] fn eq(&self, other: &PathBuf) -> bool { @@ -2724,7 +2724,7 @@ impl Path { /// /// [`Path::file_stem`]: Path::file_stem /// - #[stable(feature = "path_file_prefix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "path_file_prefix", since = "1.91.0")] #[must_use] pub fn file_prefix(&self) -> Option<&OsStr> { self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before)) @@ -2888,7 +2888,7 @@ impl Path { /// assert_eq!(path.with_added_extension("xz"), PathBuf::from("foo.tar.gz.xz")); /// assert_eq!(path.with_added_extension("").with_added_extension("txt"), PathBuf::from("foo.tar.gz.txt")); /// ``` - #[stable(feature = "path_add_extension", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "path_add_extension", since = "1.91.0")] pub fn with_added_extension>(&self, extension: S) -> PathBuf { let mut new_path = self.to_path_buf(); new_path.add_extension(extension); @@ -3405,7 +3405,7 @@ impl PartialEq for Path { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for Path { #[inline] fn eq(&self, other: &str) -> bool { @@ -3414,7 +3414,7 @@ impl cmp::PartialEq for Path { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for str { #[inline] fn eq(&self, other: &Path) -> bool { @@ -3422,7 +3422,7 @@ impl cmp::PartialEq for str { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for Path { #[inline] fn eq(&self, other: &String) -> bool { @@ -3430,7 +3430,7 @@ impl cmp::PartialEq for Path { } } -#[stable(feature = "eq_str_for_path", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "eq_str_for_path", since = "1.91.0")] impl cmp::PartialEq for String { #[inline] fn eq(&self, other: &Path) -> bool { diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md index c6f68f7a1e8..0d0acaa3bef 100644 --- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md +++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md @@ -57,7 +57,7 @@ $ rustc --target aarch64-apple-ios-macabi your-code.rs ``` The target can be differentiated from the iOS targets with the -`target_env = "macabi"` cfg (or `target_abi = "macabi"` before Rust CURRENT_RUSTC_VERSION). +`target_env = "macabi"` cfg (or `target_abi = "macabi"` before Rust 1.91.0). ```rust if cfg!(target_env = "macabi") { diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md index 3ac14704754..5de87dc349e 100644 --- a/src/doc/rustc/src/platform-support/apple-ios.md +++ b/src/doc/rustc/src/platform-support/apple-ios.md @@ -73,7 +73,7 @@ $ cargo +nightly build -Zbuild-std --target armv7s-apple-ios The simulator variants can be differentiated from the variants running on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before -Rust CURRENT_RUSTC_VERSION). +Rust 1.91.0). ```rust if cfg!(all(target_vendor = "apple", target_env = "sim")) { diff --git a/tests/ui/feature-gates/feature-gate-sanitize.stderr b/tests/ui/feature-gates/feature-gate-sanitize.stderr index 513999636a9..59e8b69de2e 100644 --- a/tests/ui/feature-gates/feature-gate-sanitize.stderr +++ b/tests/ui/feature-gates/feature-gate-sanitize.stderr @@ -4,7 +4,7 @@ error[E0557]: feature has been removed LL | #![feature(no_sanitize)] | ^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION; see for more information + = note: removed in 1.91.0; see for more information = note: renamed to sanitize(xyz = "on|off") error[E0658]: the `#[sanitize]` attribute is an experimental feature -- cgit 1.4.1-3-g733a5 From 7c00bccd3b3eb6717e3c801123107962e671e48f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 29 Mar 2025 00:53:59 +0100 Subject: Implement RFC 3631 --- compiler/rustc_ast_passes/src/feature_gate.rs | 2 - compiler/rustc_passes/messages.ftl | 9 + compiler/rustc_passes/src/check_attr.rs | 53 +++-- compiler/rustc_passes/src/errors.rs | 14 +- compiler/rustc_span/src/symbol.rs | 4 + library/alloc/src/lib.rs | 29 ++- library/core/src/lib.rs | 69 ++++-- library/std/src/lib.rs | 16 +- src/librustdoc/clean/cfg.rs | 30 +++ src/librustdoc/clean/inline.rs | 15 +- src/librustdoc/clean/mod.rs | 10 +- src/librustdoc/clean/types.rs | 302 ++++++++++++++++++++------ src/librustdoc/doctest/rust.rs | 11 +- src/librustdoc/formats/cache.rs | 2 - src/librustdoc/passes/propagate_doc_cfg.rs | 134 ++++++++---- src/librustdoc/visit_ast.rs | 27 --- 16 files changed, 518 insertions(+), 209 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 9ab5b0b3547..fe9cc8e61ed 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -182,8 +182,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_doc!( "experimental" { - cfg => doc_cfg - cfg_hide => doc_cfg_hide masked => doc_masked notable_trait => doc_notable_trait } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 870e0a90b54..19014f37c66 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -143,6 +143,15 @@ passes_doc_attribute_not_attribute = passes_doc_cfg_hide_takes_list = `#[doc(cfg_hide(...))]` takes a list of attributes +passes_doc_auto_cfg_expects_hide_or_show = + `only "hide" or "show" are allowed in "#[doc(auto_cfg(...))]"` + +passes_doc_auto_cfg_hide_show_expects_list = + `#![doc(auto_cfg({$attr_name}(...)))]` only expects a list of items + +passes_doc_auto_cfg_wrong_literal = + `expected boolean for #[doc(auto_cfg = ...)]` + passes_doc_expect_str = doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")] diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 007353f136d..3dc232a35ec 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1160,16 +1160,43 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes. - /// - fn check_doc_cfg_hide(&self, meta: &MetaItemInner, hir_id: HirId) { - if meta.meta_item_list().is_none() { - self.tcx.emit_node_span_lint( - INVALID_DOC_ATTRIBUTES, - hir_id, - meta.span(), - errors::DocCfgHideTakesList, - ); + /// Check that the `#![doc(auto_cfg(..))]` attribute has expected input. + fn check_doc_auto_cfg(&self, meta: &MetaItemInner, hir_id: HirId) { + let MetaItemInner::MetaItem(meta) = meta else { + unreachable!(); + }; + match &meta.kind { + MetaItemKind::Word => {} + MetaItemKind::NameValue(lit) => { + if !matches!(lit.kind, LitKind::Bool(_)) { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span, + errors::DocAutoCfgWrongLiteral, + ); + } + } + MetaItemKind::List(list) => { + for item in list { + let Some(attr_name) = item.name() else { continue }; + if attr_name != sym::hide && attr_name != sym::show { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span, + errors::DocAutoCfgExpectsHideOrShow, + ); + } else if item.meta_item_list().is_none() { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + meta.span, + errors::DocAutoCfgHideShowExpectsList { attr_name: attr_name.as_str() }, + ); + } + } + } } } @@ -1245,10 +1272,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_attr_crate_level(attr, style, meta, hir_id); } - Some(sym::cfg_hide) => { - if self.check_attr_crate_level(attr, style, meta, hir_id) { - self.check_doc_cfg_hide(meta, hir_id); - } + Some(sym::auto_cfg) => { + self.check_doc_auto_cfg(meta, hir_id); } Some(sym::inline | sym::no_inline) => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index cfd6b9e6dff..6cc0bd6ce48 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -309,8 +309,18 @@ pub(crate) struct DocTestLiteral; pub(crate) struct DocTestTakesList; #[derive(LintDiagnostic)] -#[diag(passes_doc_cfg_hide_takes_list)] -pub(crate) struct DocCfgHideTakesList; +#[diag(passes_doc_auto_cfg_wrong_literal)] +pub(crate) struct DocAutoCfgWrongLiteral; + +#[derive(LintDiagnostic)] +#[diag(passes_doc_auto_cfg_expects_hide_or_show)] +pub(crate) struct DocAutoCfgExpectsHideOrShow; + +#[derive(LintDiagnostic)] +#[diag(passes_doc_auto_cfg_hide_show_expects_list)] +pub(crate) struct DocAutoCfgHideShowExpectsList<'a> { + pub attr_name: &'a str, +} #[derive(LintDiagnostic)] #[diag(passes_doc_test_unknown_any)] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index faf32523baa..e80a98994db 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -545,6 +545,7 @@ symbols! { attributes, audit_that, augmented_assignments, + auto_cfg, auto_traits, autodiff, autodiff_forward, @@ -1149,6 +1150,8 @@ symbols! { hashset_iter_ty, hexagon_target_feature, hidden, + hidden_cfg, + hide, hint, homogeneous_aggregate, host, @@ -1987,6 +1990,7 @@ symbols! { shl_assign, shorter_tail_lifetimes, should_panic, + show, shr, shr_assign, sig_dfl, diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index cba1ce40f75..243fdc2e843 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -64,14 +64,27 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))) )] -#![doc(cfg_hide( - not(test), - no_global_oom_handling, - not(no_global_oom_handling), - not(no_rc), - not(no_sync), - target_has_atomic = "ptr" -))] +#![cfg_attr( + bootstrap, + doc(cfg_hide( + not(test), + no_global_oom_handling, + not(no_global_oom_handling), + not(no_rc), + not(no_sync), + target_has_atomic = "ptr" + )) +)] +#![cfg_attr( + not(bootstrap), + doc(auto_cfg(hide( + test, + no_global_oom_handling, + no_rc, + no_sync, + target_has_atomic = "ptr" + ))) +)] #![doc(rust_logo)] #![feature(rustdoc_internals)] #![no_std] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 5d52bfb1b12..32a3d6c7042 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -51,27 +51,54 @@ test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] #![doc(rust_logo)] -#![doc(cfg_hide( - no_fp_fmt_parse, - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64", - target_has_atomic = "8", - target_has_atomic = "16", - target_has_atomic = "32", - target_has_atomic = "64", - target_has_atomic = "ptr", - target_has_atomic_equal_alignment = "8", - target_has_atomic_equal_alignment = "16", - target_has_atomic_equal_alignment = "32", - target_has_atomic_equal_alignment = "64", - target_has_atomic_equal_alignment = "ptr", - target_has_atomic_load_store = "8", - target_has_atomic_load_store = "16", - target_has_atomic_load_store = "32", - target_has_atomic_load_store = "64", - target_has_atomic_load_store = "ptr", -))] +#![cfg_attr( + bootstrap, + doc(cfg_hide( + no_fp_fmt_parse, + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64", + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr", + target_has_atomic_equal_alignment = "8", + target_has_atomic_equal_alignment = "16", + target_has_atomic_equal_alignment = "32", + target_has_atomic_equal_alignment = "64", + target_has_atomic_equal_alignment = "ptr", + target_has_atomic_load_store = "8", + target_has_atomic_load_store = "16", + target_has_atomic_load_store = "32", + target_has_atomic_load_store = "64", + target_has_atomic_load_store = "ptr", + )) +)] +#![cfg_attr( + not(bootstrap), + doc(auto_cfg(hide( + no_fp_fmt_parse, + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64", + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr", + target_has_atomic_equal_alignment = "8", + target_has_atomic_equal_alignment = "16", + target_has_atomic_equal_alignment = "32", + target_has_atomic_equal_alignment = "64", + target_has_atomic_equal_alignment = "ptr", + target_has_atomic_load_store = "8", + target_has_atomic_load_store = "16", + target_has_atomic_load_store = "32", + target_has_atomic_load_store = "64", + target_has_atomic_load_store = "ptr", + ))) +)] #![no_core] #![rustc_coherence_is_core] #![rustc_preserve_ub_checks] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 233e41aa345..93c91b61525 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -235,7 +235,21 @@ test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] #![doc(rust_logo)] -#![doc(cfg_hide(not(test), no_global_oom_handling, not(no_global_oom_handling)))] +#![cfg_attr( + bootstrap, + doc(cfg_hide( + not(test), + no_global_oom_handling, + not(no_global_oom_handling) + )) +)] +#![cfg_attr( + not(bootstrap), + doc(auto_cfg(hide( + test, + no_global_oom_handling, + ))) +)] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 8feca1367fc..aa614b73dea 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -256,6 +256,36 @@ impl Cfg { fn omit_preposition(&self) -> bool { matches!(self, Cfg::True | Cfg::False) } + + pub(crate) fn strip_hidden(&self, hidden: &FxHashSet) -> Option { + match self { + Self::True | Self::False => Some(self.clone()), + Self::Cfg(..) => { + if !hidden.contains(self) { + Some(self.clone()) + } else { + None + } + } + Self::Not(cfg) => { + if let Some(cfg) = cfg.strip_hidden(hidden) { + Some(Self::Not(Box::new(cfg))) + } else { + None + } + } + Self::Any(cfgs) => { + let cfgs = + cfgs.iter().filter_map(|cfg| cfg.strip_hidden(hidden)).collect::>(); + if cfgs.is_empty() { None } else { Some(Self::Any(cfgs)) } + } + Self::All(cfgs) => { + let cfgs = + cfgs.iter().filter_map(|cfg| cfg.strip_hidden(hidden)).collect::>(); + if cfgs.is_empty() { None } else { Some(Self::All(cfgs)) } + } + } + } } impl ops::Not for Cfg { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 8461e15c6c3..8ffa6033c9b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -19,10 +19,10 @@ use tracing::{debug, trace}; use super::{Item, extract_cfg_from_attrs}; use crate::clean::{ - self, Attributes, ImplKind, ItemId, Type, clean_bound_vars, clean_generics, clean_impl_item, - clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_poly_fn_sig, - clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type, clean_ty_generics, - clean_variant_def, utils, + self, Attributes, CfgInfo, ImplKind, ItemId, Type, clean_bound_vars, clean_generics, + clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty, + clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type, + clean_ty_generics, clean_variant_def, utils, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -409,6 +409,7 @@ pub(crate) fn merge_attrs( cx: &mut DocContext<'_>, old_attrs: &[hir::Attribute], new_attrs: Option<(&[hir::Attribute], Option)>, + cfg_info: &mut CfgInfo, ) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), // always insert them first. This ensure that re-export @@ -423,12 +424,12 @@ pub(crate) fn merge_attrs( } else { Attributes::from_hir(&both) }, - extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg), + extract_cfg_from_attrs(both.iter(), cx.tcx, cfg_info), ) } else { ( Attributes::from_hir(old_attrs), - extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg), + extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, cfg_info), ) } } @@ -604,7 +605,7 @@ pub(crate) fn build_impl( }); } - let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs); + let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs, &mut CfgInfo::default()); trace!("merged_attrs={merged_attrs:?}"); trace!( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0afb969d5c8..c6339dd4755 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -212,18 +212,10 @@ fn generate_item_with_correct_attrs( // We only keep the item's attributes. target_attrs.iter().map(|attr| (Cow::Borrowed(attr), None)).collect() }; - let cfg = extract_cfg_from_attrs( - attrs.iter().map(move |(attr, _)| match attr { - Cow::Borrowed(attr) => *attr, - Cow::Owned(attr) => attr, - }), - cx.tcx, - &cx.cache.hidden_cfg, - ); let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false); let name = renamed.or(Some(name)); - let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, cfg); + let mut item = Item::from_def_id_and_attrs_and_parts(def_id, name, kind, attrs, None); // FIXME (GuillaumeGomez): Should we also make `inline_stmt_id` a `Vec` instead of an `Option`? item.inner.inline_stmt_id = import_ids.first().copied(); item diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index ff513c71035..63e8357801c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -6,7 +6,8 @@ use std::{fmt, iter}; use arrayvec::ArrayVec; use itertools::Either; use rustc_abi::{ExternAbi, VariantIdx}; -use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_ast::ast::{LitKind, MetaItemInner, MetaItemKind}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; @@ -467,7 +468,7 @@ impl Item { name, kind, Attributes::from_hir(hir_attrs), - extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg), + None, ) } @@ -902,30 +903,6 @@ impl ItemKind { | AttributeItem => [].iter(), } } - - /// Returns `true` if this item does not appear inside an impl block. - pub(crate) fn is_non_assoc(&self) -> bool { - matches!( - self, - StructItem(_) - | UnionItem(_) - | EnumItem(_) - | TraitItem(_) - | ModuleItem(_) - | ExternCrateItem { .. } - | FunctionItem(_) - | TypeAliasItem(_) - | StaticItem(_) - | ConstantItem(_) - | TraitAliasItem(_) - | ForeignFunctionItem(_, _) - | ForeignStaticItem(_, _) - | ForeignTypeItem - | MacroItem(_) - | ProcMacroItem(_) - | PrimitiveItem(_) - ) - } } #[derive(Clone, Debug)] @@ -945,14 +922,85 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator>( .flatten() } +#[derive(Clone, Debug)] +pub(crate) struct CfgInfo { + hidden_cfg: FxHashSet, + current_cfg: Cfg, + doc_auto_cfg_active: bool, + parent_is_doc_cfg: bool, +} + +impl Default for CfgInfo { + fn default() -> Self { + Self { + hidden_cfg: [ + Cfg::Cfg(sym::test, None), + Cfg::Cfg(sym::doc, None), + Cfg::Cfg(sym::doctest, None), + ] + .into_iter() + .collect(), + current_cfg: Cfg::True, + doc_auto_cfg_active: true, + parent_is_doc_cfg: false, + } + } +} + +fn show_hide_show_conflict_error( + tcx: TyCtxt<'_>, + item_span: rustc_span::Span, + previous: rustc_span::Span, +) { + let mut diag = tcx.sess.dcx().struct_span_err( + item_span, + format!( + "same `cfg` was in `auto_cfg(hide(...))` and `auto_cfg(show(...))` on the same item" + ), + ); + diag.span_note(previous, "first change was here"); + diag.emit(); +} + +fn handle_auto_cfg_hide_show( + tcx: TyCtxt<'_>, + cfg_info: &mut CfgInfo, + sub_attr: &MetaItemInner, + is_show: bool, + new_show_attrs: &mut FxHashMap<(Symbol, Option), rustc_span::Span>, + new_hide_attrs: &mut FxHashMap<(Symbol, Option), rustc_span::Span>, +) { + if let MetaItemInner::MetaItem(item) = sub_attr + && let MetaItemKind::List(items) = &item.kind + { + for item in items { + // Cfg parsing errors should already have been reported in `rustc_passes::check_attr`. + if let Ok(Cfg::Cfg(key, value)) = Cfg::parse(item) { + if is_show { + if let Some(span) = new_hide_attrs.get(&(key, value)) { + show_hide_show_conflict_error(tcx, item.span(), *span); + } else { + new_show_attrs.insert((key, value), item.span()); + } + cfg_info.hidden_cfg.remove(&Cfg::Cfg(key, value)); + } else { + if let Some(span) = new_show_attrs.get(&(key, value)) { + show_hide_show_conflict_error(tcx, item.span(), *span); + } else { + new_hide_attrs.insert((key, value), item.span()); + } + cfg_info.hidden_cfg.insert(Cfg::Cfg(key, value)); + } + } + } + } +} + pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator + Clone>( attrs: I, tcx: TyCtxt<'_>, - hidden_cfg: &FxHashSet, + cfg_info: &mut CfgInfo, ) -> Option> { - let doc_cfg_active = tcx.features().doc_cfg(); - let doc_auto_cfg_active = tcx.features().doc_auto_cfg(); - fn single(it: T) -> Option { let mut iter = it.into_iter(); let item = iter.next()?; @@ -962,56 +1010,168 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator Some(item) } - let mut cfg = if doc_cfg_active || doc_auto_cfg_active { - let mut doc_cfg = attrs - .clone() - .filter(|attr| attr.has_name(sym::doc)) - .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) - .filter(|attr| attr.has_name(sym::cfg)) - .peekable(); - if doc_cfg.peek().is_some() && doc_cfg_active { - let sess = tcx.sess; - - doc_cfg.fold(Cfg::True, |mut cfg, item| { - if let Some(cfg_mi) = - item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess)) + let mut new_show_attrs = FxHashMap::default(); + let mut new_hide_attrs = FxHashMap::default(); + + let mut doc_cfg = attrs + .clone() + .filter(|attr| attr.has_name(sym::doc)) + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) + .filter(|attr| attr.has_name(sym::cfg)) + .peekable(); + // If the item uses `doc(cfg(...))`, then we ignore the other `cfg(...)` attributes. + if doc_cfg.peek().is_some() { + let sess = tcx.sess; + // We overwrite existing `cfg`. + if !cfg_info.parent_is_doc_cfg { + cfg_info.current_cfg = Cfg::True; + cfg_info.parent_is_doc_cfg = true; + } + for attr in doc_cfg { + if let Some(cfg_mi) = + attr.meta_item().and_then(|attr| rustc_expand::config::parse_cfg(attr, sess)) + { + match Cfg::parse(cfg_mi) { + Ok(new_cfg) => cfg_info.current_cfg &= new_cfg, + Err(e) => { + sess.dcx().span_err(e.span, e.msg); + } + } + } + } + } else { + cfg_info.parent_is_doc_cfg = false; + } + + let mut changed_auto_active_status = None; + + // First we get all `doc(auto_cfg)` attributes. + for attr in attrs.clone() { + if let Some(ident) = attr.ident() + && ident.name == sym::doc + && let Some(attrs) = attr.meta_item_list() + { + for attr in attrs.iter().filter(|attr| attr.has_name(sym::auto_cfg)) { + let MetaItemInner::MetaItem(attr) = attr else { + continue; + }; + match &attr.kind { + MetaItemKind::Word => { + if let Some(first_change) = changed_auto_active_status { + if !cfg_info.doc_auto_cfg_active { + tcx.sess.dcx().struct_span_err( + vec![first_change, attr.span], + "`auto_cfg` was disabled and enabled more than once on the same item", + ).emit(); + return None; + } + } else { + changed_auto_active_status = Some(attr.span); + } + cfg_info.doc_auto_cfg_active = true; + } + MetaItemKind::NameValue(lit) => { + if let LitKind::Bool(value) = lit.kind { + if let Some(first_change) = changed_auto_active_status { + if cfg_info.doc_auto_cfg_active != value { + tcx.sess.dcx().struct_span_err( + vec![first_change, attr.span], + "`auto_cfg` was disabled and enabled more than once on the same item", + ).emit(); + return None; + } + } else { + changed_auto_active_status = Some(attr.span); + } + cfg_info.doc_auto_cfg_active = value; + } + } + MetaItemKind::List(sub_attrs) => { + if let Some(first_change) = changed_auto_active_status { + if !cfg_info.doc_auto_cfg_active { + tcx.sess.dcx().struct_span_err( + vec![first_change, attr.span], + "`auto_cfg` was disabled and enabled more than once on the same item", + ).emit(); + return None; + } + } else { + changed_auto_active_status = Some(attr.span); + } + // Whatever happens next, the feature is enabled again. + cfg_info.doc_auto_cfg_active = true; + for sub_attr in sub_attrs.iter() { + if let Some(ident) = sub_attr.ident() + && (ident.name == sym::show || ident.name == sym::hide) + { + handle_auto_cfg_hide_show( + tcx, + cfg_info, + &sub_attr, + ident.name == sym::show, + &mut new_show_attrs, + &mut new_hide_attrs, + ); + } + } + } + } + } + } + } + + // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because + // `doc(cfg())` overrides `cfg()`). + for attr in attrs { + let Some(ident) = attr.ident() else { continue }; + match ident.name { + sym::cfg | sym::cfg_trace if !cfg_info.parent_is_doc_cfg => { + if let Some(attr) = single(attr.meta_item_list()?) + && let Ok(new_cfg) = Cfg::parse(&attr) { - match Cfg::parse(cfg_mi) { - Ok(new_cfg) => cfg &= new_cfg, - Err(e) => { - sess.dcx().span_err(e.span, e.msg); + cfg_info.current_cfg &= new_cfg; + } + } + // treat #[target_feature(enable = "feat")] attributes as if they were + // #[doc(cfg(target_feature = "feat"))] attributes as well + sym::target_feature + if let Some(attrs) = attr.meta_item_list() => + { + for attr in attrs { + if attr.has_name(sym::enable) && attr.value_str().is_some() { + // Clone `enable = "feat"`, change to `target_feature = "feat"`. + // Unwrap is safe because `value_str` succeeded above. + let mut meta = attr.meta_item().unwrap().clone(); + meta.path = + ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature)); + + if let Ok(feat_cfg) = Cfg::parse(&ast::MetaItemInner::MetaItem(meta)) { + cfg_info.current_cfg &= feat_cfg; } } } - cfg - }) - } else if doc_auto_cfg_active { - // If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because - // `doc(cfg())` overrides `cfg()`). - attrs - .clone() - .filter(|attr| attr.has_name(sym::cfg_trace)) - .filter_map(|attr| single(attr.meta_item_list()?)) - .filter_map(|attr| Cfg::parse_without(attr.meta_item()?, hidden_cfg).ok().flatten()) - .fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg) + } + _ => {} + } + } + + // If `doc(auto_cfg)` feature is disabled and `doc(cfg())` wasn't used, there is nothing + // to be done here. + if !cfg_info.doc_auto_cfg_active && !cfg_info.parent_is_doc_cfg { + None + } else if cfg_info.parent_is_doc_cfg { + if cfg_info.current_cfg == Cfg::True { + None } else { - Cfg::True + Some(Arc::new(cfg_info.current_cfg.clone())) } } else { - Cfg::True - }; - - // treat #[target_feature(enable = "feat")] attributes as if they were - // #[doc(cfg(target_feature = "feat"))] attributes as well - if let Some(features) = - find_attr!(attrs, AttributeKind::TargetFeature { features, .. } => features) - { - for (feature, _) in features { - cfg &= Cfg::Cfg(sym::target_feature, Some(*feature)); + // Since we always want to collect all `cfg` items, we remove the hidden ones afterward. + match cfg_info.current_cfg.strip_hidden(&cfg_info.hidden_cfg) { + None | Some(Cfg::True) => None, + Some(cfg) => Some(Arc::new(cfg)), } } - - if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) } } pub(crate) trait NestedAttributesExt { diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index f5ec828187a..b9367b88005 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -5,7 +5,6 @@ use std::env; use std::sync::Arc; use rustc_ast_pretty::pprust; -use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; use rustc_middle::hir::nested_filter; @@ -15,7 +14,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym}; use super::{DocTestVisitor, ScrapedDocTest}; -use crate::clean::{Attributes, extract_cfg_from_attrs}; +use crate::clean::{Attributes, CfgInfo, extract_cfg_from_attrs}; use crate::html::markdown::{self, ErrorCodes, LangString, MdRelLine}; struct RustCollector { @@ -120,9 +119,11 @@ impl HirCollector<'_> { nested: F, ) { let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); - if let Some(ref cfg) = - extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default()) - && !cfg.matches(&self.tcx.sess.psess) + if let Some(ref cfg) = extract_cfg_from_attrs( + ast_attrs.iter(), + self.tcx, + &mut CfgInfo::default(), + ) && !cfg.matches(&self.tcx.sess.psess) { return; } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 29b4c4caaf8..a19d254ea95 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -125,8 +125,6 @@ pub(crate) struct Cache { /// /// Links are indexed by the DefId of the item they document. pub(crate) intra_doc_links: FxHashMap>, - /// Cfg that have been hidden via #![doc(cfg_hide(...))] - pub(crate) hidden_cfg: FxHashSet, /// Contains the list of `DefId`s which have been inlined. It is used when generating files /// to check if a stripped item should get its file generated or not: if it's inside a diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index eddafa9ba8e..957a1f56c71 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -2,11 +2,15 @@ use std::sync::Arc; +use rustc_ast::token::{Token, TokenKind}; +use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_hir::def_id::LocalDefId; +use rustc_hir::{AttrArgs, Attribute}; +use rustc_span::symbol::sym; use crate::clean::cfg::Cfg; use crate::clean::inline::{load_attrs, merge_attrs}; -use crate::clean::{Crate, Item, ItemKind}; +use crate::clean::{CfgInfo, Crate, Item, ItemKind}; use crate::core::DocContext; use crate::fold::DocFolder; use crate::passes::Pass; @@ -18,70 +22,119 @@ pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass { }; pub(crate) fn propagate_doc_cfg(cr: Crate, cx: &mut DocContext<'_>) -> Crate { - CfgPropagator { parent_cfg: None, parent: None, cx }.fold_crate(cr) + CfgPropagator { parent_cfg: None, parent: None, cx, cfg_info: CfgInfo::default() } + .fold_crate(cr) } struct CfgPropagator<'a, 'tcx> { parent_cfg: Option>, parent: Option, cx: &'a mut DocContext<'tcx>, + cfg_info: CfgInfo, } -impl CfgPropagator<'_, '_> { - // Some items need to merge their attributes with their parents' otherwise a few of them - // (mostly `cfg` ones) will be missing. - fn merge_with_parent_attributes(&mut self, item: &mut Item) { - let check_parent = match &item.kind { - // impl blocks can be in different modules with different cfg and we need to get them - // as well. - ItemKind::ImplItem(_) => false, - kind if kind.is_non_assoc() => true, - _ => return, - }; +fn should_retain(token: &TokenTree) -> bool { + // We only keep `doc(cfg)` items. + matches!( + token, + TokenTree::Token( + Token { + kind: TokenKind::Ident( + ident, + _, + ), + .. + }, + _, + ) if *ident == sym::cfg, + ) +} - let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) else { - return; - }; +fn filter_tokens_from_list(args_tokens: &TokenStream) -> Vec { + let mut tokens = Vec::with_capacity(args_tokens.len()); + let mut skip_next_delimited = false; + for token in args_tokens.iter() { + match token { + TokenTree::Delimited(..) => { + if !skip_next_delimited { + tokens.push(token.clone()); + } + skip_next_delimited = false; + } + token if should_retain(token) => { + skip_next_delimited = false; + tokens.push(token.clone()); + } + _ => { + skip_next_delimited = true; + } + } + } + tokens +} - if check_parent { - let expected_parent = self.cx.tcx.opt_local_parent(def_id); - // If parents are different, it means that `item` is a reexport and we need - // to compute the actual `cfg` by iterating through its "real" parents. - if self.parent.is_some() && self.parent == expected_parent { - return; +// We only care about `#[cfg()]` and `#[doc(cfg())]`, we discard everything else. +fn add_only_cfg_attributes(attrs: &mut Vec, new_attrs: &[Attribute]) { + for attr in new_attrs { + if attr.is_doc_comment() { + continue; + } + let mut attr = attr.clone(); + if let Attribute::Unparsed(ref mut normal) = attr + && let [ident] = &*normal.path.segments + { + let ident = ident.name; + if ident == sym::doc + && let AttrArgs::Delimited(args) = &mut normal.args + { + let tokens = filter_tokens_from_list(&args.tokens); + args.tokens = TokenStream::new(tokens); + attrs.push(attr); + } else if ident == sym::cfg_trace { + // If it's a `cfg()` attribute, we keep it. + attrs.push(attr); } } + } +} +impl CfgPropagator<'_, '_> { + // Some items need to merge their attributes with their parents' otherwise a few of them + // (mostly `cfg` ones) will be missing. + fn merge_with_parent_attributes(&mut self, item: &mut Item) { let mut attrs = Vec::new(); - let mut next_def_id = def_id; - while let Some(parent_def_id) = self.cx.tcx.opt_local_parent(next_def_id) { - attrs.extend_from_slice(load_attrs(self.cx, parent_def_id.to_def_id())); - next_def_id = parent_def_id; + // We only need to merge an item attributes with its parent's in case it's an impl as an + // impl might not be defined in the same module as the item it implements. + // + // Otherwise, `cfg_info` already tracks everything we need so nothing else to do! + if matches!(item.kind, ItemKind::ImplItem(_)) + && let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) + { + let mut next_def_id = def_id; + while let Some(parent_def_id) = self.cx.tcx.opt_local_parent(next_def_id) { + let x = load_attrs(self.cx, parent_def_id.to_def_id()); + add_only_cfg_attributes(&mut attrs, x); + next_def_id = parent_def_id; + } } - let (_, cfg) = - merge_attrs(self.cx, item.attrs.other_attrs.as_slice(), Some((&attrs, None))); + let (_, cfg) = merge_attrs( + self.cx, + item.attrs.other_attrs.as_slice(), + Some((&attrs, None)), + &mut self.cfg_info, + ); item.inner.cfg = cfg; } } impl DocFolder for CfgPropagator<'_, '_> { fn fold_item(&mut self, mut item: Item) -> Option { + let old_cfg_info = self.cfg_info.clone(); let old_parent_cfg = self.parent_cfg.clone(); self.merge_with_parent_attributes(&mut item); - - let new_cfg = match (self.parent_cfg.take(), item.inner.cfg.take()) { - (None, None) => None, - (Some(rc), None) | (None, Some(rc)) => Some(rc), - (Some(mut a), Some(b)) => { - let b = Arc::try_unwrap(b).unwrap_or_else(|rc| Cfg::clone(&rc)); - *Arc::make_mut(&mut a) &= b; - Some(a) - } - }; - self.parent_cfg = new_cfg.clone(); - item.inner.cfg = new_cfg; + self.parent_cfg = item.inner.cfg.clone(); let old_parent = if let Some(def_id) = item.item_id.as_def_id().and_then(|def_id| def_id.as_local()) { @@ -90,6 +143,7 @@ impl DocFolder for CfgPropagator<'_, '_> { self.parent.take() }; let result = self.fold_item_recur(item); + self.cfg_info = old_cfg_info; self.parent_cfg = old_parent_cfg; self.parent = old_parent; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index cd28322f590..ac67871b0cb 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -17,7 +17,6 @@ use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_span::symbol::{Symbol, kw, sym}; use tracing::debug; -use crate::clean::cfg::Cfg; use crate::clean::utils::{inherits_doc_hidden, should_ignore_res}; use crate::clean::{NestedAttributesExt, hir_attr_lists, reexport_chain}; use crate::core; @@ -178,32 +177,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - self.cx.cache.hidden_cfg = self - .cx - .tcx - .hir_attrs(CRATE_HIR_ID) - .iter() - .filter(|attr| attr.has_name(sym::doc)) - .flat_map(|attr| attr.meta_item_list().into_iter().flatten()) - .filter(|attr| attr.has_name(sym::cfg_hide)) - .flat_map(|attr| { - attr.meta_item_list() - .unwrap_or(&[]) - .iter() - .filter_map(|attr| { - Cfg::parse(attr) - .map_err(|e| self.cx.sess().dcx().span_err(e.span, e.msg)) - .ok() - }) - .collect::>() - }) - .chain([ - Cfg::Cfg(sym::test, None), - Cfg::Cfg(sym::doc, None), - Cfg::Cfg(sym::doctest, None), - ]) - .collect(); - self.cx.cache.exact_paths = self.exact_paths; top_level_module } -- cgit 1.4.1-3-g733a5 From 63aefe0737d0df886955f5a3aa68db865cd97f1b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 1 Apr 2025 17:24:28 +0200 Subject: Strenghten checks for `doc(auto_cfg(show/hide))` attributes --- compiler/rustc_passes/messages.ftl | 3 +++ compiler/rustc_passes/src/check_attr.rs | 15 ++++++++++++++- compiler/rustc_passes/src/errors.rs | 6 ++++++ library/alloc/src/lib.rs | 1 - library/std/src/lib.rs | 8 +------- tests/rustdoc-ui/lints/doc_cfg_hide.rs | 1 + tests/rustdoc-ui/lints/doc_cfg_hide.stderr | 8 +++++++- 7 files changed, 32 insertions(+), 10 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 19014f37c66..8326ddaf194 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -149,6 +149,9 @@ passes_doc_auto_cfg_expects_hide_or_show = passes_doc_auto_cfg_hide_show_expects_list = `#![doc(auto_cfg({$attr_name}(...)))]` only expects a list of items +passes_doc_auto_cfg_hide_show_unexpected_item = + `#![doc(auto_cfg({$attr_name}(...)))]` only accepts identifiers or key/values items + passes_doc_auto_cfg_wrong_literal = `expected boolean for #[doc(auto_cfg = ...)]` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3dc232a35ec..38b67e2f9dc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1187,7 +1187,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> { meta.span, errors::DocAutoCfgExpectsHideOrShow, ); - } else if item.meta_item_list().is_none() { + } else if let Some(list) = item.meta_item_list() { + for item in list { + if item.meta_item_list().is_some() { + self.tcx.emit_node_span_lint( + INVALID_DOC_ATTRIBUTES, + hir_id, + item.span(), + errors::DocAutoCfgHideShowUnexpectedItem { + attr_name: attr_name.as_str(), + }, + ); + } + } + } else { self.tcx.emit_node_span_lint( INVALID_DOC_ATTRIBUTES, hir_id, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 6cc0bd6ce48..1d2428c4f9a 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -322,6 +322,12 @@ pub(crate) struct DocAutoCfgHideShowExpectsList<'a> { pub attr_name: &'a str, } +#[derive(LintDiagnostic)] +#[diag(passes_doc_auto_cfg_hide_show_unexpected_item)] +pub(crate) struct DocAutoCfgHideShowUnexpectedItem<'a> { + pub attr_name: &'a str, +} + #[derive(LintDiagnostic)] #[diag(passes_doc_test_unknown_any)] pub(crate) struct DocTestUnknownAny { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 243fdc2e843..dc5d243e882 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -78,7 +78,6 @@ #![cfg_attr( not(bootstrap), doc(auto_cfg(hide( - test, no_global_oom_handling, no_rc, no_sync, diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 93c91b61525..ecd354f599e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -243,13 +243,7 @@ not(no_global_oom_handling) )) )] -#![cfg_attr( - not(bootstrap), - doc(auto_cfg(hide( - test, - no_global_oom_handling, - ))) -)] +#![cfg_attr(not(bootstrap), doc(auto_cfg(hide(no_global_oom_handling))))] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.rs b/tests/rustdoc-ui/lints/doc_cfg_hide.rs index abf56318479..4f2625d00ce 100644 --- a/tests/rustdoc-ui/lints/doc_cfg_hide.rs +++ b/tests/rustdoc-ui/lints/doc_cfg_hide.rs @@ -1,2 +1,3 @@ #![doc(auto_cfg(hide = "test"))] //~ ERROR #![doc(auto_cfg(hide))] //~ ERROR +#![doc(auto_cfg(hide(not(windows))))] //~ ERROR diff --git a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr index bb0e52eb666..22501d63c3f 100644 --- a/tests/rustdoc-ui/lints/doc_cfg_hide.stderr +++ b/tests/rustdoc-ui/lints/doc_cfg_hide.stderr @@ -12,5 +12,11 @@ error: `#![doc(auto_cfg(hide(...)))]` only expects a list of items LL | #![doc(auto_cfg(hide))] | ^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or key/values items + --> $DIR/doc_cfg_hide.rs:3:22 + | +LL | #![doc(auto_cfg(hide(not(windows))))] + | ^^^^^^^^^^^^ + +error: aborting due to 3 previous errors -- cgit 1.4.1-3-g733a5 From fccba2c341b65b62f513c0b7ee8842f134f3cbcd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 29 May 2025 21:54:16 +0200 Subject: Remove `doc_cfg_hide` feature --- compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_span/src/symbol.rs | 1 - library/alloc/src/lib.rs | 2 +- library/core/src/lib.rs | 2 +- library/std/src/lib.rs | 3 ++- 5 files changed, 4 insertions(+), 6 deletions(-) (limited to 'library/std/src') diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 6ef0df72365..4dc961cb927 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -476,8 +476,6 @@ declare_features! ( (unstable, doc_auto_cfg, "1.58.0", Some(43781)), /// Allows `#[doc(cfg(...))]`. (unstable, doc_cfg, "1.21.0", Some(43781)), - /// Allows `#[doc(cfg_hide(...))]`. - (unstable, doc_cfg_hide, "1.57.0", Some(43781)), /// Allows `#[doc(masked)]`. (unstable, doc_masked, "1.21.0", Some(44027)), /// Allows features to allow target_feature to better interact with traits. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 18c3faed932..79f00e2e94d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -878,7 +878,6 @@ symbols! { doc_alias, doc_auto_cfg, doc_cfg, - doc_cfg_hide, doc_keyword, doc_masked, doc_notable_trait, diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index dc5d243e882..24d7e6216a0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -207,7 +207,7 @@ // // Rustdoc features: #![feature(doc_cfg)] -#![feature(doc_cfg_hide)] +#![cfg_attr(bootstrap, feature(doc_cfg_hide))] // Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]` // blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 32a3d6c7042..b1e559065fe 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -161,6 +161,7 @@ // // Language features: // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(doc_cfg_hide))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] @@ -176,7 +177,6 @@ #![feature(deprecated_suggestion)] #![feature(derive_const)] #![feature(doc_cfg)] -#![feature(doc_cfg_hide)] #![feature(doc_notable_trait)] #![feature(extern_types)] #![feature(f16)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ecd354f599e..ff997ff7603 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -278,6 +278,8 @@ // tidy-alphabetical-start // stabilization was reverted after it hit beta +#![cfg_attr(bootstrap, feature(doc_cfg_hide))] +#![cfg_attr(not(bootstrap), feature(autodiff))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] @@ -293,7 +295,6 @@ #![feature(decl_macro)] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] -#![feature(doc_cfg_hide)] #![feature(doc_masked)] #![feature(doc_notable_trait)] #![feature(dropck_eyepatch)] -- cgit 1.4.1-3-g733a5 From a7ed9bf6c7473827b7c876679a2a633facec09b8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Jun 2025 22:19:33 +0200 Subject: fmt --- library/alloc/src/lib.rs | 7 +------ library/std/src/lib.rs | 6 +----- src/librustdoc/doctest/rust.rs | 8 +++----- 3 files changed, 5 insertions(+), 16 deletions(-) (limited to 'library/std/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 24d7e6216a0..7499db8bf2c 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -77,12 +77,7 @@ )] #![cfg_attr( not(bootstrap), - doc(auto_cfg(hide( - no_global_oom_handling, - no_rc, - no_sync, - target_has_atomic = "ptr" - ))) + doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr"))) )] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ff997ff7603..c8fe5c55e97 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -237,11 +237,7 @@ #![doc(rust_logo)] #![cfg_attr( bootstrap, - doc(cfg_hide( - not(test), - no_global_oom_handling, - not(no_global_oom_handling) - )) + doc(cfg_hide(not(test), no_global_oom_handling, not(no_global_oom_handling))) )] #![cfg_attr(not(bootstrap), doc(auto_cfg(hide(no_global_oom_handling))))] // Don't link to std. We are std. diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index b9367b88005..4d3f976c2a6 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -119,11 +119,9 @@ impl HirCollector<'_> { nested: F, ) { let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); - if let Some(ref cfg) = extract_cfg_from_attrs( - ast_attrs.iter(), - self.tcx, - &mut CfgInfo::default(), - ) && !cfg.matches(&self.tcx.sess.psess) + if let Some(ref cfg) = + extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &mut CfgInfo::default()) + && !cfg.matches(&self.tcx.sess.psess) { return; } -- cgit 1.4.1-3-g733a5 From ec00723ba153c72124f8271b6dc15540f23e6832 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Jun 2025 13:34:41 +0200 Subject: Fix autodiff feature activation --- library/std/src/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index c8fe5c55e97..501c22cfb49 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -275,7 +275,6 @@ // stabilization was reverted after it hit beta #![cfg_attr(bootstrap, feature(doc_cfg_hide))] -#![cfg_attr(not(bootstrap), feature(autodiff))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] -- cgit 1.4.1-3-g733a5 From 254a2139f6c4b251d9210843d2e7d7952ef9f40d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 10 Jun 2025 17:44:14 +0200 Subject: Remove `cfg(bootstrap)` for `doc_cfg` feature following #141925 --- library/alloc/src/lib.rs | 17 +----------- library/core/src/lib.rs | 70 +++++++++++++++--------------------------------- library/std/src/lib.rs | 7 +---- 3 files changed, 23 insertions(+), 71 deletions(-) (limited to 'library/std/src') diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7499db8bf2c..fc3266b7479 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -64,21 +64,7 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/", test(no_crate_inject, attr(allow(unused_variables), deny(warnings))) )] -#![cfg_attr( - bootstrap, - doc(cfg_hide( - not(test), - no_global_oom_handling, - not(no_global_oom_handling), - not(no_rc), - not(no_sync), - target_has_atomic = "ptr" - )) -)] -#![cfg_attr( - not(bootstrap), - doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr"))) -)] +#![doc(auto_cfg(hide(no_global_oom_handling, no_rc, no_sync, target_has_atomic = "ptr")))] #![doc(rust_logo)] #![feature(rustdoc_internals)] #![no_std] @@ -202,7 +188,6 @@ // // Rustdoc features: #![feature(doc_cfg)] -#![cfg_attr(bootstrap, feature(doc_cfg_hide))] // Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]` // blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad // that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index b1e559065fe..54adf97f100 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -51,54 +51,27 @@ test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] #![doc(rust_logo)] -#![cfg_attr( - bootstrap, - doc(cfg_hide( - no_fp_fmt_parse, - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64", - target_has_atomic = "8", - target_has_atomic = "16", - target_has_atomic = "32", - target_has_atomic = "64", - target_has_atomic = "ptr", - target_has_atomic_equal_alignment = "8", - target_has_atomic_equal_alignment = "16", - target_has_atomic_equal_alignment = "32", - target_has_atomic_equal_alignment = "64", - target_has_atomic_equal_alignment = "ptr", - target_has_atomic_load_store = "8", - target_has_atomic_load_store = "16", - target_has_atomic_load_store = "32", - target_has_atomic_load_store = "64", - target_has_atomic_load_store = "ptr", - )) -)] -#![cfg_attr( - not(bootstrap), - doc(auto_cfg(hide( - no_fp_fmt_parse, - target_pointer_width = "16", - target_pointer_width = "32", - target_pointer_width = "64", - target_has_atomic = "8", - target_has_atomic = "16", - target_has_atomic = "32", - target_has_atomic = "64", - target_has_atomic = "ptr", - target_has_atomic_equal_alignment = "8", - target_has_atomic_equal_alignment = "16", - target_has_atomic_equal_alignment = "32", - target_has_atomic_equal_alignment = "64", - target_has_atomic_equal_alignment = "ptr", - target_has_atomic_load_store = "8", - target_has_atomic_load_store = "16", - target_has_atomic_load_store = "32", - target_has_atomic_load_store = "64", - target_has_atomic_load_store = "ptr", - ))) -)] +#![doc(auto_cfg(hide( + no_fp_fmt_parse, + target_pointer_width = "16", + target_pointer_width = "32", + target_pointer_width = "64", + target_has_atomic = "8", + target_has_atomic = "16", + target_has_atomic = "32", + target_has_atomic = "64", + target_has_atomic = "ptr", + target_has_atomic_equal_alignment = "8", + target_has_atomic_equal_alignment = "16", + target_has_atomic_equal_alignment = "32", + target_has_atomic_equal_alignment = "64", + target_has_atomic_equal_alignment = "ptr", + target_has_atomic_load_store = "8", + target_has_atomic_load_store = "16", + target_has_atomic_load_store = "32", + target_has_atomic_load_store = "64", + target_has_atomic_load_store = "ptr", +)))] #![no_core] #![rustc_coherence_is_core] #![rustc_preserve_ub_checks] @@ -161,7 +134,6 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(doc_cfg_hide))] #![feature(abi_unadjusted)] #![feature(adt_const_params)] #![feature(allow_internal_unsafe)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 501c22cfb49..61b7d170b8b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -235,11 +235,7 @@ test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))) )] #![doc(rust_logo)] -#![cfg_attr( - bootstrap, - doc(cfg_hide(not(test), no_global_oom_handling, not(no_global_oom_handling))) -)] -#![cfg_attr(not(bootstrap), doc(auto_cfg(hide(no_global_oom_handling))))] +#![doc(auto_cfg(hide(no_global_oom_handling)))] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind @@ -274,7 +270,6 @@ // tidy-alphabetical-start // stabilization was reverted after it hit beta -#![cfg_attr(bootstrap, feature(doc_cfg_hide))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] -- cgit 1.4.1-3-g733a5 From 760ed37769c4902c97c874d324978472ce02f9ba Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sat, 27 Sep 2025 08:25:47 -0600 Subject: redox: switch to colon as path separator --- library/std/src/sys/pal/unix/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f0b6068e06c..7c9f3b7992f 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -16,7 +16,7 @@ use crate::{fmt, io, iter, mem, ptr, slice, str}; const TMPBUF_SZ: usize = 128; -const PATH_SEPARATOR: u8 = if cfg!(target_os = "redox") { b';' } else { b':' }; +const PATH_SEPARATOR: u8 = b':'; unsafe extern "C" { #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] -- cgit 1.4.1-3-g733a5 From 19d0e728496afa1ba6a5f9817201b7d57337c14c Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 27 Sep 2025 20:38:45 +0100 Subject: fix build for android --- library/std/src/os/net/linux_ext/tcp.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'library/std/src') diff --git a/library/std/src/os/net/linux_ext/tcp.rs b/library/std/src/os/net/linux_ext/tcp.rs index dbefc91a979..3f9b2bd3f4b 100644 --- a/library/std/src/os/net/linux_ext/tcp.rs +++ b/library/std/src/os/net/linux_ext/tcp.rs @@ -4,6 +4,7 @@ use crate::sealed::Sealed; use crate::sys_common::AsInner; +#[cfg(target_os = "linux")] use crate::time::Duration; use crate::{io, net}; -- cgit 1.4.1-3-g733a5 From 3a20a4d0a5463edb5fca2adfbe0522042a9ce752 Mon Sep 17 00:00:00 2001 From: Sebastian Speitel Date: Sun, 28 Sep 2025 00:51:57 +0200 Subject: Fix typo --- library/std/src/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'library/std/src') diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index a45edd08e8c..25a4661a0bc 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -3234,7 +3234,7 @@ fn inlined_slow_read_byte(reader: &mut R) -> Option> { } } -// Used by `BufReader::spec_read_byte`, for which the `inline(ever)` is +// Used by `BufReader::spec_read_byte`, for which the `inline(never)` is // important. #[inline(never)] fn uninlined_slow_read_byte(reader: &mut R) -> Option> { -- cgit 1.4.1-3-g733a5