diff --git a/.gitattributes b/.gitattributes index d29c15fe712f3..8700d5d6dcff1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,6 +5,7 @@ *.h rust *.rs rust diff=rust *.fixed linguist-language=Rust +*.pp linguist-language=Rust *.mir linguist-language=Rust src/etc/installer/gfx/* binary src/vendor/** -text diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3f28dc7a1efae..843d5ca61dddb 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1462,7 +1462,8 @@ impl BackendRepr { !self.is_unsized() } - /// Returns `true` if this is a single signed integer scalar + /// Returns `true` if this is a single signed integer scalar. + /// Sanity check: panics if this is not a scalar type (see PR #70189). #[inline] pub fn is_signed(&self) -> bool { match self { diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs index dbe1540364ad8..860629b08e19b 100644 --- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs +++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs @@ -2,7 +2,7 @@ use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(), + llvm_target: "armv5te-unknown-linux-gnueabi".into(), metadata: TargetMetadata { description: Some("Armv5TE Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs index 0955b3debea00..c14bfbf46d21d 100644 --- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs @@ -4,7 +4,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mips-unknown-linux-uclibc".into(), + llvm_target: "mips-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs index 08c4347fe0145..f0056799d66f6 100644 --- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs @@ -2,7 +2,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base}; pub(crate) fn target() -> Target { Target { - llvm_target: "mipsel-unknown-linux-uclibc".into(), + llvm_target: "mipsel-unknown-linux-gnu".into(), metadata: TargetMetadata { description: Some("MIPS (LE) Linux with uClibc".into()), tier: Some(3), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs index a034a9fb24453..4107249dcf1e3 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs @@ -8,7 +8,7 @@ pub(crate) fn target() -> Target { base.panic_strategy = PanicStrategy::Abort; Target { - llvm_target: "x86_64-unknown-l4re-uclibc".into(), + llvm_target: "x86_64-unknown-l4re-gnu".into(), metadata: TargetMetadata { description: None, tier: Some(3), diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 1a320b316a41a..e789601a409af 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -495,7 +495,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "move_cell", since = "1.17.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] #[rustc_confusables("swap")] pub const fn replace(&self, val: T) -> T { // SAFETY: This can cause data races if called from a separate thread, @@ -537,7 +537,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get(&self) -> T { // SAFETY: This can cause data races if called from a separate thread, // but `Cell` is `!Sync` so this won't happen. @@ -617,7 +617,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn get_mut(&mut self) -> &mut T { self.value.get_mut() } @@ -637,7 +637,7 @@ impl Cell { /// ``` #[inline] #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn from_mut(t: &mut T) -> &Cell { // SAFETY: `&mut` ensures unique access. unsafe { &*(t as *mut T as *const Cell) } @@ -695,7 +695,7 @@ impl Cell<[T]> { /// assert_eq!(slice_cell.len(), 3); /// ``` #[stable(feature = "as_cell", since = "1.37.0")] - #[rustc_const_unstable(feature = "const_cell", issue = "131283")] + #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")] pub const fn as_slice_of_cells(&self) -> &[Cell] { // SAFETY: `Cell` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T]> as *const [Cell]) } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index fa98db693066a..801baf3d99072 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2370,7 +2370,7 @@ impl AsInner for DirEntry { #[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_file>(path: P) -> io::Result<()> { - fs_imp::unlink(path.as_ref()) + fs_imp::remove_file(path.as_ref()) } /// Given a path, queries the file system to get information about a file, @@ -2409,7 +2409,7 @@ pub fn remove_file>(path: P) -> io::Result<()> { #[doc(alias = "stat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn metadata>(path: P) -> io::Result { - fs_imp::stat(path.as_ref()).map(Metadata) + fs_imp::metadata(path.as_ref()).map(Metadata) } /// Queries the metadata about a file without following symlinks. @@ -2444,7 +2444,7 @@ pub fn metadata>(path: P) -> io::Result { #[doc(alias = "lstat")] #[stable(feature = "symlink_metadata", since = "1.1.0")] pub fn symlink_metadata>(path: P) -> io::Result { - fs_imp::lstat(path.as_ref()).map(Metadata) + fs_imp::symlink_metadata(path.as_ref()).map(Metadata) } /// Renames a file or directory to a new name, replacing the original file if @@ -2598,7 +2598,7 @@ pub fn copy, Q: AsRef>(from: P, to: Q) -> io::Result { #[doc(alias = "CreateHardLink", alias = "linkat")] #[stable(feature = "rust1", since = "1.0.0")] pub fn hard_link, Q: AsRef>(original: P, link: Q) -> io::Result<()> { - fs_imp::link(original.as_ref(), link.as_ref()) + fs_imp::hard_link(original.as_ref(), link.as_ref()) } /// Creates a new symbolic link on the filesystem. @@ -2664,7 +2664,7 @@ pub fn soft_link, Q: AsRef>(original: P, link: Q) -> io::Re /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_link>(path: P) -> io::Result { - fs_imp::readlink(path.as_ref()) + fs_imp::read_link(path.as_ref()) } /// Returns the canonical, absolute form of a path with all intermediate @@ -2840,7 +2840,7 @@ pub fn create_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "rmdir", alias = "RemoveDirectory")] #[stable(feature = "rust1", since = "1.0.0")] pub fn remove_dir>(path: P) -> io::Result<()> { - fs_imp::rmdir(path.as_ref()) + fs_imp::remove_dir(path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use @@ -2967,7 +2967,7 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { #[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")] #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir>(path: P) -> io::Result { - fs_imp::readdir(path.as_ref()).map(ReadDir) + fs_imp::read_dir(path.as_ref()).map(ReadDir) } /// Changes the permissions found on a file or a directory. @@ -3003,7 +3003,7 @@ pub fn read_dir>(path: P) -> io::Result { #[doc(alias = "chmod", alias = "SetFileAttributes")] #[stable(feature = "set_permissions", since = "1.1.0")] pub fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { - fs_imp::set_perm(path.as_ref(), perm.0) + fs_imp::set_permissions(path.as_ref(), perm.0) } impl DirBuilder { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ad005833ad53e..9dcedaa13f661 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(extended_varargs_abi_support)] #![feature(f128)] #![feature(f16)] +#![feature(ffi_const)] #![feature(formatting_options)] #![feature(if_let_guard)] #![feature(intra_doc_pointers)] diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index c2e19eb393a16..3b176d0d16c44 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -1,28 +1,115 @@ #![deny(unsafe_op_in_unsafe_fn)] +use crate::io; +use crate::path::{Path, PathBuf}; + pub mod common; cfg_if::cfg_if! { if #[cfg(target_family = "unix")] { mod unix; - pub use unix::*; + use unix as imp; + pub use unix::{chown, fchown, lchown}; + #[cfg(not(target_os = "fuchsia"))] + pub use unix::chroot; + pub(crate) use unix::debug_assert_fd_is_open; + #[cfg(any(target_os = "linux", target_os = "android"))] + pub(crate) use unix::CachedFileMetadata; + use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path; } else if #[cfg(target_os = "windows")] { mod windows; - pub use windows::*; + use windows as imp; + pub use windows::{symlink_inner, junction_point}; } else if #[cfg(target_os = "hermit")] { mod hermit; - pub use hermit::*; + use hermit as imp; } else if #[cfg(target_os = "solid_asp3")] { mod solid; - pub use solid::*; + use solid as imp; } else if #[cfg(target_os = "uefi")] { mod uefi; - pub use uefi::*; + use uefi as imp; } else if #[cfg(target_os = "wasi")] { mod wasi; - pub use wasi::*; + use wasi as imp; } else { mod unsupported; - pub use unsupported::*; + use unsupported as imp; } } + +// FIXME: Replace this with platform-specific path conversion functions. +#[cfg(not(target_family = "unix"))] +#[inline] +pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> io::Result { + f(path) +} + +pub use imp::{ + DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, + ReadDir, +}; + +pub fn read_dir(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::readdir(path) +} + +pub fn remove_file(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::unlink) +} + +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new))) +} + +pub fn remove_dir(path: &Path) -> io::Result<()> { + with_native_path(path, &imp::rmdir) +} + +pub fn remove_dir_all(path: &Path) -> io::Result<()> { + // FIXME: use with_native_path + imp::remove_dir_all(path) +} + +pub fn read_link(path: &Path) -> io::Result { + with_native_path(path, &imp::readlink) +} + +pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::symlink(original, link)) + }) +} + +pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> { + with_native_path(original, &|original| { + with_native_path(link, &|link| imp::link(original, link)) + }) +} + +pub fn metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::stat) +} + +pub fn symlink_metadata(path: &Path) -> io::Result { + with_native_path(path, &imp::lstat) +} + +pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> { + with_native_path(path, &|path| imp::set_perm(path, perm.clone())) +} + +pub fn canonicalize(path: &Path) -> io::Result { + with_native_path(path, &imp::canonicalize) +} + +pub fn copy(from: &Path, to: &Path) -> io::Result { + // FIXME: use with_native_path + imp::copy(from, to) +} + +pub fn exists(path: &Path) -> io::Result { + // FIXME: use with_native_path + imp::exists(path) +} diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 60e6559fa6b99..87865be0387d5 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -926,7 +926,7 @@ impl DirEntry { miri ))] pub fn metadata(&self) -> io::Result { - lstat(&self.path()) + run_path_with_cstr(&self.path(), &lstat) } #[cfg(any( @@ -1657,7 +1657,7 @@ impl fmt::Debug for File { fn get_path(fd: c_int) -> Option { let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - readlink(&p).ok() + run_path_with_cstr(&p, &readlink).ok() } #[cfg(any(target_vendor = "apple", target_os = "netbsd"))] @@ -1675,7 +1675,7 @@ impl fmt::Debug for File { // fallback to procfs as last resort let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); - return readlink(&p).ok(); + return run_path_with_cstr(&p, &readlink).ok() } else { return None; } @@ -1830,127 +1830,106 @@ pub fn readdir(path: &Path) -> io::Result { } } -pub fn unlink(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())) +pub fn unlink(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()) } -pub fn rename(old: &Path, new: &Path) -> io::Result<()> { - run_path_with_cstr(old, &|old| { - run_path_with_cstr(new, &|new| { - cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) - }) - }) +pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ()) } -pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())) +pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> { + cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()) } -pub fn rmdir(p: &Path) -> io::Result<()> { - run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())) +pub fn rmdir(p: &CStr) -> io::Result<()> { + cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()) } -pub fn readlink(p: &Path) -> io::Result { - run_path_with_cstr(p, &|c_path| { - let p = c_path.as_ptr(); - - let mut buf = Vec::with_capacity(256); +pub fn readlink(c_path: &CStr) -> io::Result { + let p = c_path.as_ptr(); - loop { - let buf_read = - cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? - as usize; + let mut buf = Vec::with_capacity(256); - unsafe { - buf.set_len(buf_read); - } + loop { + let buf_read = + cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize; - if buf_read != buf.capacity() { - buf.shrink_to_fit(); + unsafe { + buf.set_len(buf_read); + } - return Ok(PathBuf::from(OsString::from_vec(buf))); - } + if buf_read != buf.capacity() { + buf.shrink_to_fit(); - // Trigger the internal buffer resizing logic of `Vec` by requiring - // more space than the current capacity. The length is guaranteed to be - // the same as the capacity due to the if statement above. - buf.reserve(1); + return Ok(PathBuf::from(OsString::from_vec(buf))); } - }) + + // Trigger the internal buffer resizing logic of `Vec` by requiring + // more space than the current capacity. The length is guaranteed to be + // the same as the capacity due to the if statement above. + buf.reserve(1); + } } -pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) - }) - }) +pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> { + cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ()) } -pub fn link(original: &Path, link: &Path) -> io::Result<()> { - run_path_with_cstr(original, &|original| { - run_path_with_cstr(link, &|link| { - cfg_if::cfg_if! { - if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { - // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves - // it implementation-defined whether `link` follows symlinks, so rely on the - // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. - // Android has `linkat` on newer versions, but we happen to know `link` - // always has the correct behavior, so it's here as well. - cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; - } else { - // Where we can, use `linkat` instead of `link`; see the comment above - // this one for details on why. - cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; - } - } - Ok(()) - }) - }) +pub fn link(original: &CStr, link: &CStr) -> io::Result<()> { + cfg_if::cfg_if! { + if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] { + // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves + // it implementation-defined whether `link` follows symlinks, so rely on the + // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior. + // Android has `linkat` on newer versions, but we happen to know `link` + // always has the correct behavior, so it's here as well. + cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?; + } else { + // Where we can, use `linkat` instead of `link`; see the comment above + // this one for details on why. + cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?; + } + } + Ok(()) } -pub fn stat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn stat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn lstat(p: &Path) -> io::Result { - run_path_with_cstr(p, &|p| { - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - libc::AT_FDCWD, - p.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } +pub fn lstat(p: &CStr) -> io::Result { + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; } + } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr::from_stat64(stat)) - }) + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; + Ok(FileAttr::from_stat64(stat)) } -pub fn canonicalize(p: &Path) -> io::Result { - let r = run_path_with_cstr(p, &|path| unsafe { - Ok(libc::realpath(path.as_ptr(), ptr::null_mut())) - })?; +pub fn canonicalize(path: &CStr) -> io::Result { + let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) }; if r.is_null() { return Err(io::Error::last_os_error()); } @@ -2328,19 +2307,19 @@ mod remove_dir_impl { Ok(()) } - fn remove_dir_all_modern(p: &Path) -> io::Result<()> { + fn remove_dir_all_modern(p: &CStr) -> io::Result<()> { // We cannot just call remove_dir_all_recursive() here because that would not delete a passed // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse // into symlinks. let attr = lstat(p)?; if attr.file_type().is_symlink() { - crate::fs::remove_file(p) + super::unlink(p) } else { - run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p)) + remove_dir_all_recursive(None, &p) } } pub fn remove_dir_all(p: &Path) -> io::Result<()> { - remove_dir_all_modern(p) + run_path_with_cstr(p, &remove_dir_all_modern) } } diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 30282fbf65541..f47421c67051b 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -59,11 +59,14 @@ unsafe extern "C" { #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")] #[cfg_attr(target_os = "haiku", link_name = "_errnop")] #[cfg_attr(target_os = "aix", link_name = "_Errno")] + // SAFETY: this will always return the same pointer on a given thread. + #[unsafe(ffi_const)] fn errno_location() -> *mut c_int; } /// Returns the platform-specific value of errno #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] +#[inline] pub fn errno() -> i32 { unsafe { (*errno_location()) as i32 } } @@ -72,16 +75,19 @@ pub fn errno() -> i32 { // needed for readdir and syscall! #[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))] #[allow(dead_code)] // but not all target cfgs actually end up using it +#[inline] pub fn set_errno(e: i32) { unsafe { *errno_location() = e as c_int } } #[cfg(target_os = "vxworks")] +#[inline] pub fn errno() -> i32 { unsafe { libc::errnoGet() } } #[cfg(target_os = "rtems")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -92,6 +98,7 @@ pub fn errno() -> i32 { } #[cfg(target_os = "dragonfly")] +#[inline] pub fn errno() -> i32 { unsafe extern "C" { #[thread_local] @@ -103,6 +110,7 @@ pub fn errno() -> i32 { #[cfg(target_os = "dragonfly")] #[allow(dead_code)] +#[inline] pub fn set_errno(e: i32) { unsafe extern "C" { #[thread_local] diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 68400ba0ea029..5487750405521 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1162,6 +1162,37 @@ def build_triple(self): config = self.get_toml("build") return config or default_build_triple(self.verbose) + def is_git_repository(self, repo_path): + return os.path.isdir(os.path.join(repo_path, ".git")) + + def get_latest_commit(self, repo_path, author_email): + try: + if not self.is_git_repository(repo_path): + return "" + cmd = [ + "git", + "-C", + repo_path, + "rev-list", + "--author", + author_email, + "-n1", + "HEAD", + ] + commit = subprocess.check_output(cmd, text=True).strip() + return commit if commit else "" + except subprocess.CalledProcessError: + return "" + + def get_value(self): + file_path = f"{self.rust_root}/src/stage0" + target_key = "git_merge_commit_email" + with open(file_path, "r") as file: + for line in file: + if line.startswith(f"{target_key}="): + return line.split("=", 1)[1].strip() + return None + def check_vendored_status(self): """Check that vendoring is configured properly""" # keep this consistent with the equivalent check in bootstrap: @@ -1174,7 +1205,10 @@ def check_vendored_status(self): eprint(" use vendored sources by default.") cargo_dir = os.path.join(self.rust_root, ".cargo") - url = "https://ci-artifacts.rust-lang.org/rustc-builds//rustc-nightly-src.tar.xz" + repo_path = self.rust_root + git_merge_commit_email = self.get_value() + commit = self.get_latest_commit(repo_path, git_merge_commit_email) + url = f"https://ci-artifacts.rust-lang.org/rustc-builds/{commit}/rustc-nightly-src.tar.xz" if self.use_vendored_sources: vendor_dir = os.path.join(self.rust_root, "vendor") if not os.path.exists(vendor_dir): diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index 98bb9dee76c57..1190c2646af10 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below): * `~|`: Associates the error level and message with the *same* line as the *previous comment*. This is more convenient than using multiple carets when there are multiple messages associated with the same line. +* `~v`: Associates the error level and message with the *next* error + annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv` + is three lines below the error annotation line. * `~?`: Used to match error levels and messages with errors not having line information. These can be placed on any line in the test file, but are conventionally placed at the end. @@ -273,6 +276,18 @@ fn main() { //~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023] ``` +#### Positioned above error line + +Use the `//~v` idiom with number of v's in the string to indicate the number +of lines below. This is typically used in lexer or parser tests matching on errors like unclosed +delimiter or unclosed literal happening at the end of file. + +```rust,ignore +// ignore-tidy-trailing-newlines +//~v ERROR this file contains an unclosed delimiter +fn main((ؼ +``` + #### Error without line information Use `//~?` to match an error without line information. diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index c0566ef93b924..b68f817146fd7 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -122,13 +122,17 @@ fn parse_expected( // //~| // //~^ // //~^^^^^ + // //~v + // //~vvvvv // //~? // //[rev1]~ // //[rev1,rev2]~^^ static RE: OnceLock = OnceLock::new(); let captures = RE - .get_or_init(|| Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||\^*)").unwrap()) + .get_or_init(|| { + Regex::new(r"//(?:\[(?P[\w\-,]+)])?~(?P\?|\||[v\^]*)").unwrap() + }) .captures(line)?; match (test_revision, captures.name("revs")) { @@ -164,6 +168,8 @@ fn parse_expected( (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line"))) } else if line_num_adjust == "?" { (false, None) + } else if line_num_adjust.starts_with('v') { + (false, Some(line_num + line_num_adjust.len())) } else { (false, Some(line_num - line_num_adjust.len())) }; diff --git a/tests/ui/parser/issues/issue-103451.rs b/tests/ui/parser/issues/issue-103451.rs index 6b0928229e912..687dbc632d678 100644 --- a/tests/ui/parser/issues/issue-103451.rs +++ b/tests/ui/parser/issues/issue-103451.rs @@ -1,4 +1,4 @@ -//@ error-pattern: this file contains an unclosed delimiter struct R { } +//~vv ERROR this file contains an unclosed delimiter struct S { x: [u8; R diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs index 7200ea1f1dd1f..dcc03fec545cd 100644 --- a/tests/ui/parser/issues/issue-10636-2.rs +++ b/tests/ui/parser/issues/issue-10636-2.rs @@ -1,7 +1,7 @@ -//@ error-pattern: mismatched closing delimiter: `}` // FIXME(31528) we emit a bunch of silly errors here due to continuing past the // first one. This would be easy-ish to address by better recovery in tokenisation. +//~vvvvv ERROR mismatched closing delimiter: `}` pub fn trace_option(option: Option) { option.map(|some| 42; diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs index 7952d29c26024..0c0fbd7d5929b 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs @@ -1,5 +1,4 @@ // Fixed in #66054. // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter #[Ѕ \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr index 14f5469f6af94..28fd78d660ddc 100644 --- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr +++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 | LL | #[Ѕ | - ^ diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs index a219f662cf78c..a8c7d6eb9fdd1 100644 --- a/tests/ui/parser/issues/issue-62524.rs +++ b/tests/ui/parser/issues/issue-62524.rs @@ -1,6 +1,7 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 1 previous error + #![allow(uncommon_codepoints)] +//~vv ERROR this file contains an unclosed delimiter y![ Ϥ, \ No newline at end of file diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr index d83a49aedd6e8..c1ff6e7e7158e 100644 --- a/tests/ui/parser/issues/issue-62524.stderr +++ b/tests/ui/parser/issues/issue-62524.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62524.rs:6:3 + --> $DIR/issue-62524.rs:7:3 | LL | y![ | - unclosed delimiter diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs index 9f196e4b0d614..4a8a1684a412d 100644 --- a/tests/ui/parser/issues/issue-62554.rs +++ b/tests/ui/parser/issues/issue-62554.rs @@ -1,5 +1,4 @@ -//@ error-pattern:this file contains an unclosed delimiter - fn main() {} +//~v ERROR this file contains an unclosed delimiter fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr index d4aaef1618139..50515c4c574a1 100644 --- a/tests/ui/parser/issues/issue-62554.stderr +++ b/tests/ui/parser/issues/issue-62554.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-62554.rs:5:89 + --> $DIR/issue-62554.rs:4:89 | LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { | - - - - -^ diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs index 5b1627a255372..c49cbe4b934dd 100644 --- a/tests/ui/parser/issues/issue-62894.rs +++ b/tests/ui/parser/issues/issue-62894.rs @@ -1,6 +1,6 @@ // Regression test for #62894, shouldn't crash. -//@ error-pattern: this file contains an unclosed delimiter +//~vvv ERROR this file contains an unclosed delimiter fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! fn main() {} diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs index 5c666d802fe44..a091e4eec1d92 100644 --- a/tests/ui/parser/issues/issue-62973.rs +++ b/tests/ui/parser/issues/issue-62973.rs @@ -1,8 +1,10 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: aborting due to 3 previous errors fn main() {} +//~vvv ERROR mismatched closing delimiter: `)` +//~vv ERROR mismatched closing delimiter: `)` +//~vvv ERROR this file contains an unclosed delimiter fn p() { match s { v, E { [) {) } diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr index 493183988e18b..ea3e2bebee404 100644 --- a/tests/ui/parser/issues/issue-62973.stderr +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:27 + --> $DIR/issue-62973.rs:8:27 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: mismatched closing delimiter: `)` - --> $DIR/issue-62973.rs:6:30 + --> $DIR/issue-62973.rs:8:30 | LL | fn p() { match s { v, E { [) {) } | ^^ mismatched closing delimiter @@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) } | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-62973.rs:8:2 + --> $DIR/issue-62973.rs:10:2 | LL | fn p() { match s { v, E { [) {) } | - - - - missing open `(` for this delimiter diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs index 3be9606b4edbc..48abe639e8d97 100644 --- a/tests/ui/parser/issues/issue-63116.rs +++ b/tests/ui/parser/issues/issue-63116.rs @@ -1,3 +1,4 @@ // fixed by #66361 -//@ error-pattern: aborting due to 2 previous errors +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter impl W $DIR/issue-63116.rs:3:14 + --> $DIR/issue-63116.rs:4:14 | LL | impl W $DIR/issue-63116.rs:3:18 + --> $DIR/issue-63116.rs:4:18 | LL | impl W $DIR/issue-63135.rs:3:16 + --> $DIR/issue-63135.rs:2:16 | LL | fn i(n{...,f # | - - ^ diff --git a/tests/ui/parser/issues/issue-81804.rs b/tests/ui/parser/issues/issue-81804.rs index 7c9e6e905825b..57951ca5c4bc1 100644 --- a/tests/ui/parser/issues/issue-81804.rs +++ b/tests/ui/parser/issues/issue-81804.rs @@ -1,6 +1,5 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: this file contains an unclosed delimiter - fn main() {} +//~vv ERROR mismatched closing delimiter: `}` +//~v ERROR this file contains an unclosed delimiter fn p([=(} diff --git a/tests/ui/parser/issues/issue-81804.stderr b/tests/ui/parser/issues/issue-81804.stderr index 6caaaa792b196..f12c6a61ce5ec 100644 --- a/tests/ui/parser/issues/issue-81804.stderr +++ b/tests/ui/parser/issues/issue-81804.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `}` - --> $DIR/issue-81804.rs:6:8 + --> $DIR/issue-81804.rs:5:8 | LL | fn p([=(} | ^^ mismatched closing delimiter @@ -7,7 +7,7 @@ LL | fn p([=(} | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-81804.rs:6:11 + --> $DIR/issue-81804.rs:5:11 | LL | fn p([=(} | -- ^ diff --git a/tests/ui/parser/issues/issue-81827.rs b/tests/ui/parser/issues/issue-81827.rs index a2bd345fc050e..7dfeec13022a0 100644 --- a/tests/ui/parser/issues/issue-81827.rs +++ b/tests/ui/parser/issues/issue-81827.rs @@ -1,10 +1,7 @@ -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: mismatched closing delimiter: `]` - #![crate_name="0"] - - fn main() {} +//~vv ERROR mismatched closing delimiter: `]` +//~v ERROR this file contains an unclosed delimiter fn r()->i{0|{#[cfg(r(0{]0 diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr index d12c74b4a3420..986ed6b7e70f9 100644 --- a/tests/ui/parser/issues/issue-81827.stderr +++ b/tests/ui/parser/issues/issue-81827.stderr @@ -1,5 +1,5 @@ error: mismatched closing delimiter: `]` - --> $DIR/issue-81827.rs:10:23 + --> $DIR/issue-81827.rs:7:23 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - ^^ mismatched closing delimiter @@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0 | closing delimiter possibly meant for this error: this file contains an unclosed delimiter - --> $DIR/issue-81827.rs:10:27 + --> $DIR/issue-81827.rs:7:27 | LL | fn r()->i{0|{#[cfg(r(0{]0 | - - - ^ diff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs index bced05e684a7f..6baf882701d3c 100644 --- a/tests/ui/parser/issues/issue-84104.rs +++ b/tests/ui/parser/issues/issue-84104.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter #[i=i::<ښܖ< diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs index 560475bd32c3f..452279021ab9d 100644 --- a/tests/ui/parser/issues/issue-84148-2.rs +++ b/tests/ui/parser/issues/issue-84148-2.rs @@ -1,2 +1,2 @@ -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter fn f(t:for<>t? diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs index ecc50481f65d7..0dd18435ce3ff 100644 --- a/tests/ui/parser/issues/issue-88770.rs +++ b/tests/ui/parser/issues/issue-88770.rs @@ -1,7 +1,6 @@ // Regression test for the ICE described in #88770. -//@ error-pattern:this file contains an unclosed delimiter - +//~vvvv ERROR this file contains an unclosed delimiter fn m(){print!("",(c for&g u e diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr index 5b54072d009fb..137cfea7e1d0d 100644 --- a/tests/ui/parser/issues/issue-88770.stderr +++ b/tests/ui/parser/issues/issue-88770.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/issue-88770.rs:8:3 + --> $DIR/issue-88770.rs:7:3 | LL | fn m(){print!("",(c for&g | - - - unclosed delimiter diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs index 9c57b0ebcfc3d..851919316647d 100644 --- a/tests/ui/parser/mbe_missing_right_paren.rs +++ b/tests/ui/parser/mbe_missing_right_paren.rs @@ -1,3 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter +//~v ERROR this file contains an unclosed delimiter macro_rules! abc(ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs index bbf4519a713ee..311a16c214c39 100644 --- a/tests/ui/parser/missing_right_paren.rs +++ b/tests/ui/parser/missing_right_paren.rs @@ -1,4 +1,3 @@ // ignore-tidy-trailing-newlines -//@ error-pattern: this file contains an unclosed delimiter -//@ error-pattern: aborting due to 1 previous error +//~v ERROR this file contains an unclosed delimiter fn main((ؼ \ No newline at end of file diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr index 4815f04fbce07..97ccb40a5a2a7 100644 --- a/tests/ui/parser/missing_right_paren.stderr +++ b/tests/ui/parser/missing_right_paren.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing_right_paren.rs:4:11 + --> $DIR/missing_right_paren.rs:3:11 | LL | fn main((ؼ | -- ^ diff --git a/tests/ui/parser/unbalanced-doublequote.rs b/tests/ui/parser/unbalanced-doublequote.rs index d9c936186ea07..43e23a70271b0 100644 --- a/tests/ui/parser/unbalanced-doublequote.rs +++ b/tests/ui/parser/unbalanced-doublequote.rs @@ -1,6 +1,4 @@ -//@ error-pattern: unterminated double quote string - - +//~vv ERROR unterminated double quote string fn main() { " } diff --git a/tests/ui/parser/unbalanced-doublequote.stderr b/tests/ui/parser/unbalanced-doublequote.stderr index d40b982da7c39..60057eddbb423 100644 --- a/tests/ui/parser/unbalanced-doublequote.stderr +++ b/tests/ui/parser/unbalanced-doublequote.stderr @@ -1,5 +1,5 @@ error[E0765]: unterminated double quote string - --> $DIR/unbalanced-doublequote.rs:5:5 + --> $DIR/unbalanced-doublequote.rs:3:5 | LL | / " LL | | } diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs index 6679651fe47e2..aa52fe92ac1ba 100644 --- a/tests/ui/parser/use-unclosed-brace.rs +++ b/tests/ui/parser/use-unclosed-brace.rs @@ -1,4 +1,3 @@ -//@ error-pattern: this file contains an unclosed delimiter use foo::{bar, baz; use std::fmt::Display; @@ -7,4 +6,5 @@ mod bar { } mod baz { } +//~v ERROR this file contains an unclosed delimiter fn main() {}