authorbors <bors@rust-lang.org> 2025-03-29 23:12:40 UTC
committerbors <bors@rust-lang.org> 2025-03-29 23:12:40 UTC
log2196affd0165ee2352522d33544447c61d351937
tree996a8a3ea8f0f323430ee5685d69786ea8f77a27
parent1799887bb281d1ab49287750f1950b8c738c6b77
parented1f776e5cf110d7ac10c1a78417de488e73db93

Auto merge of #139119 - matthiaskrgr:rollup-7l2ri0f, r=matthiaskrgr

Rollup of 7 pull requests Successful merges: - #137928 (stabilize const_cell) - #138431 (Fix `uclibc` LLVM target triples) - #138832 (Start using `with_native_path` in `std::sys::fs`) - #139081 (std: deduplicate `errno` accesses) - #139100 (compiletest: Support matching diagnostics on lines below) - #139105 (`BackendRepr::is_signed`: comment why this may panics) - #139106 (Mark .pp files as Rust) r? `@ghost` `@rustbot` modify labels: rollup

43 files changed, 264 insertions(+), 173 deletions(-)

.gitattributes+1
......@@ -5,6 +5,7 @@
55*.h rust
66*.rs rust diff=rust
77*.fixed linguist-language=Rust
8*.pp linguist-language=Rust
89*.mir linguist-language=Rust
910src/etc/installer/gfx/* binary
1011src/vendor/** -text
compiler/rustc_abi/src/lib.rs+2-1
......@@ -1462,7 +1462,8 @@ impl BackendRepr {
14621462 !self.is_unsized()
14631463 }
14641464
1465 /// Returns `true` if this is a single signed integer scalar
1465 /// Returns `true` if this is a single signed integer scalar.
1466 /// Sanity check: panics if this is not a scalar type (see PR #70189).
14661467 #[inline]
14671468 pub fn is_signed(&self) -> bool {
14681469 match self {
compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs+1-1
......@@ -2,7 +2,7 @@ use crate::spec::{FloatAbi, Target, TargetMetadata, TargetOptions, base};
22
33pub(crate) fn target() -> Target {
44 Target {
5 llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
5 llvm_target: "armv5te-unknown-linux-gnueabi".into(),
66 metadata: TargetMetadata {
77 description: Some("Armv5TE Linux with uClibc".into()),
88 tier: Some(3),
compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs+1-1
......@@ -4,7 +4,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base};
44
55pub(crate) fn target() -> Target {
66 Target {
7 llvm_target: "mips-unknown-linux-uclibc".into(),
7 llvm_target: "mips-unknown-linux-gnu".into(),
88 metadata: TargetMetadata {
99 description: Some("MIPS Linux with uClibc".into()),
1010 tier: Some(3),
compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs+1-1
......@@ -2,7 +2,7 @@ use crate::spec::{Target, TargetMetadata, TargetOptions, base};
22
33pub(crate) fn target() -> Target {
44 Target {
5 llvm_target: "mipsel-unknown-linux-uclibc".into(),
5 llvm_target: "mipsel-unknown-linux-gnu".into(),
66 metadata: TargetMetadata {
77 description: Some("MIPS (LE) Linux with uClibc".into()),
88 tier: Some(3),
compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs+1-1
......@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
88 base.panic_strategy = PanicStrategy::Abort;
99
1010 Target {
11 llvm_target: "x86_64-unknown-l4re-uclibc".into(),
11 llvm_target: "x86_64-unknown-l4re-gnu".into(),
1212 metadata: TargetMetadata {
1313 description: None,
1414 tier: Some(3),
library/core/src/cell.rs+5-5
......@@ -495,7 +495,7 @@ impl<T> Cell<T> {
495495 /// ```
496496 #[inline]
497497 #[stable(feature = "move_cell", since = "1.17.0")]
498 #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
498 #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
499499 #[rustc_confusables("swap")]
500500 pub const fn replace(&self, val: T) -> T {
501501 // SAFETY: This can cause data races if called from a separate thread,
......@@ -537,7 +537,7 @@ impl<T: Copy> Cell<T> {
537537 /// ```
538538 #[inline]
539539 #[stable(feature = "rust1", since = "1.0.0")]
540 #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
540 #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
541541 pub const fn get(&self) -> T {
542542 // SAFETY: This can cause data races if called from a separate thread,
543543 // but `Cell` is `!Sync` so this won't happen.
......@@ -617,7 +617,7 @@ impl<T: ?Sized> Cell<T> {
617617 /// ```
618618 #[inline]
619619 #[stable(feature = "cell_get_mut", since = "1.11.0")]
620 #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
620 #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
621621 pub const fn get_mut(&mut self) -> &mut T {
622622 self.value.get_mut()
623623 }
......@@ -637,7 +637,7 @@ impl<T: ?Sized> Cell<T> {
637637 /// ```
638638 #[inline]
639639 #[stable(feature = "as_cell", since = "1.37.0")]
640 #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
640 #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
641641 pub const fn from_mut(t: &mut T) -> &Cell<T> {
642642 // SAFETY: `&mut` ensures unique access.
643643 unsafe { &*(t as *mut T as *const Cell<T>) }
......@@ -695,7 +695,7 @@ impl<T> Cell<[T]> {
695695 /// assert_eq!(slice_cell.len(), 3);
696696 /// ```
697697 #[stable(feature = "as_cell", since = "1.37.0")]
698 #[rustc_const_unstable(feature = "const_cell", issue = "131283")]
698 #[rustc_const_stable(feature = "const_cell", since = "CURRENT_RUSTC_VERSION")]
699699 pub const fn as_slice_of_cells(&self) -> &[Cell<T>] {
700700 // SAFETY: `Cell<T>` has the same memory layout as `T`.
701701 unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
library/std/src/fs.rs+8-8
......@@ -2370,7 +2370,7 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
23702370#[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")]
23712371#[stable(feature = "rust1", since = "1.0.0")]
23722372pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
2373 fs_imp::unlink(path.as_ref())
2373 fs_imp::remove_file(path.as_ref())
23742374}
23752375
23762376/// Given a path, queries the file system to get information about a file,
......@@ -2409,7 +2409,7 @@ pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
24092409#[doc(alias = "stat")]
24102410#[stable(feature = "rust1", since = "1.0.0")]
24112411pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
2412 fs_imp::stat(path.as_ref()).map(Metadata)
2412 fs_imp::metadata(path.as_ref()).map(Metadata)
24132413}
24142414
24152415/// Queries the metadata about a file without following symlinks.
......@@ -2444,7 +2444,7 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
24442444#[doc(alias = "lstat")]
24452445#[stable(feature = "symlink_metadata", since = "1.1.0")]
24462446pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
2447 fs_imp::lstat(path.as_ref()).map(Metadata)
2447 fs_imp::symlink_metadata(path.as_ref()).map(Metadata)
24482448}
24492449
24502450/// Renames a file or directory to a new name, replacing the original file if
......@@ -2598,7 +2598,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
25982598#[doc(alias = "CreateHardLink", alias = "linkat")]
25992599#[stable(feature = "rust1", since = "1.0.0")]
26002600pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
2601 fs_imp::link(original.as_ref(), link.as_ref())
2601 fs_imp::hard_link(original.as_ref(), link.as_ref())
26022602}
26032603
26042604/// Creates a new symbolic link on the filesystem.
......@@ -2664,7 +2664,7 @@ pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Re
26642664/// ```
26652665#[stable(feature = "rust1", since = "1.0.0")]
26662666pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
2667 fs_imp::readlink(path.as_ref())
2667 fs_imp::read_link(path.as_ref())
26682668}
26692669
26702670/// Returns the canonical, absolute form of a path with all intermediate
......@@ -2840,7 +2840,7 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
28402840#[doc(alias = "rmdir", alias = "RemoveDirectory")]
28412841#[stable(feature = "rust1", since = "1.0.0")]
28422842pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
2843 fs_imp::rmdir(path.as_ref())
2843 fs_imp::remove_dir(path.as_ref())
28442844}
28452845
28462846/// Removes a directory at this path, after removing all its contents. Use
......@@ -2967,7 +2967,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
29672967#[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")]
29682968#[stable(feature = "rust1", since = "1.0.0")]
29692969pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
2970 fs_imp::readdir(path.as_ref()).map(ReadDir)
2970 fs_imp::read_dir(path.as_ref()).map(ReadDir)
29712971}
29722972
29732973/// Changes the permissions found on a file or a directory.
......@@ -3003,7 +3003,7 @@ pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
30033003#[doc(alias = "chmod", alias = "SetFileAttributes")]
30043004#[stable(feature = "set_permissions", since = "1.1.0")]
30053005pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
3006 fs_imp::set_perm(path.as_ref(), perm.0)
3006 fs_imp::set_permissions(path.as_ref(), perm.0)
30073007}
30083008
30093009impl DirBuilder {
library/std/src/lib.rs+1
......@@ -297,6 +297,7 @@
297297#![feature(extended_varargs_abi_support)]
298298#![feature(f128)]
299299#![feature(f16)]
300#![feature(ffi_const)]
300301#![feature(formatting_options)]
301302#![feature(if_let_guard)]
302303#![feature(intra_doc_pointers)]
library/std/src/sys/fs/mod.rs+94-7
......@@ -1,28 +1,115 @@
11#![deny(unsafe_op_in_unsafe_fn)]
22
3use crate::io;
4use crate::path::{Path, PathBuf};
5
36pub mod common;
47
58cfg_if::cfg_if! {
69 if #[cfg(target_family = "unix")] {
710 mod unix;
8 pub use unix::*;
11 use unix as imp;
12 pub use unix::{chown, fchown, lchown};
13 #[cfg(not(target_os = "fuchsia"))]
14 pub use unix::chroot;
15 pub(crate) use unix::debug_assert_fd_is_open;
16 #[cfg(any(target_os = "linux", target_os = "android"))]
17 pub(crate) use unix::CachedFileMetadata;
18 use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
919 } else if #[cfg(target_os = "windows")] {
1020 mod windows;
11 pub use windows::*;
21 use windows as imp;
22 pub use windows::{symlink_inner, junction_point};
1223 } else if #[cfg(target_os = "hermit")] {
1324 mod hermit;
14 pub use hermit::*;
25 use hermit as imp;
1526 } else if #[cfg(target_os = "solid_asp3")] {
1627 mod solid;
17 pub use solid::*;
28 use solid as imp;
1829 } else if #[cfg(target_os = "uefi")] {
1930 mod uefi;
20 pub use uefi::*;
31 use uefi as imp;
2132 } else if #[cfg(target_os = "wasi")] {
2233 mod wasi;
23 pub use wasi::*;
34 use wasi as imp;
2435 } else {
2536 mod unsupported;
26 pub use unsupported::*;
37 use unsupported as imp;
2738 }
2839}
40
41// FIXME: Replace this with platform-specific path conversion functions.
42#[cfg(not(target_family = "unix"))]
43#[inline]
44pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
45 f(path)
46}
47
48pub use imp::{
49 DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
50 ReadDir,
51};
52
53pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
54 // FIXME: use with_native_path
55 imp::readdir(path)
56}
57
58pub fn remove_file(path: &Path) -> io::Result<()> {
59 with_native_path(path, &imp::unlink)
60}
61
62pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
63 with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
64}
65
66pub fn remove_dir(path: &Path) -> io::Result<()> {
67 with_native_path(path, &imp::rmdir)
68}
69
70pub fn remove_dir_all(path: &Path) -> io::Result<()> {
71 // FIXME: use with_native_path
72 imp::remove_dir_all(path)
73}
74
75pub fn read_link(path: &Path) -> io::Result<PathBuf> {
76 with_native_path(path, &imp::readlink)
77}
78
79pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
80 with_native_path(original, &|original| {
81 with_native_path(link, &|link| imp::symlink(original, link))
82 })
83}
84
85pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
86 with_native_path(original, &|original| {
87 with_native_path(link, &|link| imp::link(original, link))
88 })
89}
90
91pub fn metadata(path: &Path) -> io::Result<FileAttr> {
92 with_native_path(path, &imp::stat)
93}
94
95pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
96 with_native_path(path, &imp::lstat)
97}
98
99pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
100 with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
101}
102
103pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
104 with_native_path(path, &imp::canonicalize)
105}
106
107pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
108 // FIXME: use with_native_path
109 imp::copy(from, to)
110}
111
112pub fn exists(path: &Path) -> io::Result<bool> {
113 // FIXME: use with_native_path
114 imp::exists(path)
115}
library/std/src/sys/fs/unix.rs+79-100
......@@ -926,7 +926,7 @@ impl DirEntry {
926926 miri
927927 ))]
928928 pub fn metadata(&self) -> io::Result<FileAttr> {
929 lstat(&self.path())
929 run_path_with_cstr(&self.path(), &lstat)
930930 }
931931
932932 #[cfg(any(
......@@ -1657,7 +1657,7 @@ impl fmt::Debug for File {
16571657 fn get_path(fd: c_int) -> Option<PathBuf> {
16581658 let mut p = PathBuf::from("/proc/self/fd");
16591659 p.push(&fd.to_string());
1660 readlink(&p).ok()
1660 run_path_with_cstr(&p, &readlink).ok()
16611661 }
16621662
16631663 #[cfg(any(target_vendor = "apple", target_os = "netbsd"))]
......@@ -1675,7 +1675,7 @@ impl fmt::Debug for File {
16751675 // fallback to procfs as last resort
16761676 let mut p = PathBuf::from("/proc/self/fd");
16771677 p.push(&fd.to_string());
1678 return readlink(&p).ok();
1678 return run_path_with_cstr(&p, &readlink).ok()
16791679 } else {
16801680 return None;
16811681 }
......@@ -1830,127 +1830,106 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> {
18301830 }
18311831}
18321832
1833pub fn unlink(p: &Path) -> io::Result<()> {
1834 run_path_with_cstr(p, &|p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()))
1833pub fn unlink(p: &CStr) -> io::Result<()> {
1834 cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ())
18351835}
18361836
1837pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
1838 run_path_with_cstr(old, &|old| {
1839 run_path_with_cstr(new, &|new| {
1840 cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
1841 })
1842 })
1837pub fn rename(old: &CStr, new: &CStr) -> io::Result<()> {
1838 cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
18431839}
18441840
1845pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
1846 run_path_with_cstr(p, &|p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()))
1841pub fn set_perm(p: &CStr, perm: FilePermissions) -> io::Result<()> {
1842 cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ())
18471843}
18481844
1849pub fn rmdir(p: &Path) -> io::Result<()> {
1850 run_path_with_cstr(p, &|p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()))
1845pub fn rmdir(p: &CStr) -> io::Result<()> {
1846 cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ())
18511847}
18521848
1853pub fn readlink(p: &Path) -> io::Result<PathBuf> {
1854 run_path_with_cstr(p, &|c_path| {
1855 let p = c_path.as_ptr();
1856
1857 let mut buf = Vec::with_capacity(256);
1849pub fn readlink(c_path: &CStr) -> io::Result<PathBuf> {
1850 let p = c_path.as_ptr();
18581851
1859 loop {
1860 let buf_read =
1861 cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })?
1862 as usize;
1852 let mut buf = Vec::with_capacity(256);
18631853
1864 unsafe {
1865 buf.set_len(buf_read);
1866 }
1854 loop {
1855 let buf_read =
1856 cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
18671857
1868 if buf_read != buf.capacity() {
1869 buf.shrink_to_fit();
1858 unsafe {
1859 buf.set_len(buf_read);
1860 }
18701861
1871 return Ok(PathBuf::from(OsString::from_vec(buf)));
1872 }
1862 if buf_read != buf.capacity() {
1863 buf.shrink_to_fit();
18731864
1874 // Trigger the internal buffer resizing logic of `Vec` by requiring
1875 // more space than the current capacity. The length is guaranteed to be
1876 // the same as the capacity due to the if statement above.
1877 buf.reserve(1);
1865 return Ok(PathBuf::from(OsString::from_vec(buf)));
18781866 }
1879 })
1867
1868 // Trigger the internal buffer resizing logic of `Vec` by requiring
1869 // more space than the current capacity. The length is guaranteed to be
1870 // the same as the capacity due to the if statement above.
1871 buf.reserve(1);
1872 }
18801873}
18811874
1882pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
1883 run_path_with_cstr(original, &|original| {
1884 run_path_with_cstr(link, &|link| {
1885 cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
1886 })
1887 })
1875pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> {
1876 cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
18881877}
18891878
1890pub fn link(original: &Path, link: &Path) -> io::Result<()> {
1891 run_path_with_cstr(original, &|original| {
1892 run_path_with_cstr(link, &|link| {
1893 cfg_if::cfg_if! {
1894 if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
1895 // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
1896 // it implementation-defined whether `link` follows symlinks, so rely on the
1897 // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
1898 // Android has `linkat` on newer versions, but we happen to know `link`
1899 // always has the correct behavior, so it's here as well.
1900 cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
1901 } else {
1902 // Where we can, use `linkat` instead of `link`; see the comment above
1903 // this one for details on why.
1904 cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
1905 }
1906 }
1907 Ok(())
1908 })
1909 })
1879pub fn link(original: &CStr, link: &CStr) -> io::Result<()> {
1880 cfg_if::cfg_if! {
1881 if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita", target_env = "nto70"))] {
1882 // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
1883 // it implementation-defined whether `link` follows symlinks, so rely on the
1884 // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
1885 // Android has `linkat` on newer versions, but we happen to know `link`
1886 // always has the correct behavior, so it's here as well.
1887 cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
1888 } else {
1889 // Where we can, use `linkat` instead of `link`; see the comment above
1890 // this one for details on why.
1891 cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
1892 }
1893 }
1894 Ok(())
19101895}
19111896
1912pub fn stat(p: &Path) -> io::Result<FileAttr> {
1913 run_path_with_cstr(p, &|p| {
1914 cfg_has_statx! {
1915 if let Some(ret) = unsafe { try_statx(
1916 libc::AT_FDCWD,
1917 p.as_ptr(),
1918 libc::AT_STATX_SYNC_AS_STAT,
1919 libc::STATX_BASIC_STATS | libc::STATX_BTIME,
1920 ) } {
1921 return ret;
1922 }
1897pub fn stat(p: &CStr) -> io::Result<FileAttr> {
1898 cfg_has_statx! {
1899 if let Some(ret) = unsafe { try_statx(
1900 libc::AT_FDCWD,
1901 p.as_ptr(),
1902 libc::AT_STATX_SYNC_AS_STAT,
1903 libc::STATX_BASIC_STATS | libc::STATX_BTIME,
1904 ) } {
1905 return ret;
19231906 }
1907 }
19241908
1925 let mut stat: stat64 = unsafe { mem::zeroed() };
1926 cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
1927 Ok(FileAttr::from_stat64(stat))
1928 })
1909 let mut stat: stat64 = unsafe { mem::zeroed() };
1910 cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
1911 Ok(FileAttr::from_stat64(stat))
19291912}
19301913
1931pub fn lstat(p: &Path) -> io::Result<FileAttr> {
1932 run_path_with_cstr(p, &|p| {
1933 cfg_has_statx! {
1934 if let Some(ret) = unsafe { try_statx(
1935 libc::AT_FDCWD,
1936 p.as_ptr(),
1937 libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
1938 libc::STATX_BASIC_STATS | libc::STATX_BTIME,
1939 ) } {
1940 return ret;
1941 }
1914pub fn lstat(p: &CStr) -> io::Result<FileAttr> {
1915 cfg_has_statx! {
1916 if let Some(ret) = unsafe { try_statx(
1917 libc::AT_FDCWD,
1918 p.as_ptr(),
1919 libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
1920 libc::STATX_BASIC_STATS | libc::STATX_BTIME,
1921 ) } {
1922 return ret;
19421923 }
1924 }
19431925
1944 let mut stat: stat64 = unsafe { mem::zeroed() };
1945 cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
1946 Ok(FileAttr::from_stat64(stat))
1947 })
1926 let mut stat: stat64 = unsafe { mem::zeroed() };
1927 cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
1928 Ok(FileAttr::from_stat64(stat))
19481929}
19491930
1950pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
1951 let r = run_path_with_cstr(p, &|path| unsafe {
1952 Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
1953 })?;
1931pub fn canonicalize(path: &CStr) -> io::Result<PathBuf> {
1932 let r = unsafe { libc::realpath(path.as_ptr(), ptr::null_mut()) };
19541933 if r.is_null() {
19551934 return Err(io::Error::last_os_error());
19561935 }
......@@ -2328,19 +2307,19 @@ mod remove_dir_impl {
23282307 Ok(())
23292308 }
23302309
2331 fn remove_dir_all_modern(p: &Path) -> io::Result<()> {
2310 fn remove_dir_all_modern(p: &CStr) -> io::Result<()> {
23322311 // We cannot just call remove_dir_all_recursive() here because that would not delete a passed
23332312 // symlink. No need to worry about races, because remove_dir_all_recursive() does not recurse
23342313 // into symlinks.
23352314 let attr = lstat(p)?;
23362315 if attr.file_type().is_symlink() {
2337 crate::fs::remove_file(p)
2316 super::unlink(p)
23382317 } else {
2339 run_path_with_cstr(p, &|p| remove_dir_all_recursive(None, &p))
2318 remove_dir_all_recursive(None, &p)
23402319 }
23412320 }
23422321
23432322 pub fn remove_dir_all(p: &Path) -> io::Result<()> {
2344 remove_dir_all_modern(p)
2323 run_path_with_cstr(p, &remove_dir_all_modern)
23452324 }
23462325}
library/std/src/sys/pal/unix/os.rs+8
......@@ -59,11 +59,14 @@ unsafe extern "C" {
5959 #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
6060 #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
6161 #[cfg_attr(target_os = "aix", link_name = "_Errno")]
62 // SAFETY: this will always return the same pointer on a given thread.
63 #[unsafe(ffi_const)]
6264 fn errno_location() -> *mut c_int;
6365}
6466
6567/// Returns the platform-specific value of errno
6668#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
69#[inline]
6770pub fn errno() -> i32 {
6871 unsafe { (*errno_location()) as i32 }
6972}
......@@ -72,16 +75,19 @@ pub fn errno() -> i32 {
7275// needed for readdir and syscall!
7376#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))]
7477#[allow(dead_code)] // but not all target cfgs actually end up using it
78#[inline]
7579pub fn set_errno(e: i32) {
7680 unsafe { *errno_location() = e as c_int }
7781}
7882
7983#[cfg(target_os = "vxworks")]
84#[inline]
8085pub fn errno() -> i32 {
8186 unsafe { libc::errnoGet() }
8287}
8388
8489#[cfg(target_os = "rtems")]
90#[inline]
8591pub fn errno() -> i32 {
8692 unsafe extern "C" {
8793 #[thread_local]
......@@ -92,6 +98,7 @@ pub fn errno() -> i32 {
9298}
9399
94100#[cfg(target_os = "dragonfly")]
101#[inline]
95102pub fn errno() -> i32 {
96103 unsafe extern "C" {
97104 #[thread_local]
......@@ -103,6 +110,7 @@ pub fn errno() -> i32 {
103110
104111#[cfg(target_os = "dragonfly")]
105112#[allow(dead_code)]
113#[inline]
106114pub fn set_errno(e: i32) {
107115 unsafe extern "C" {
108116 #[thread_local]
src/doc/rustc-dev-guide/src/tests/ui.md+15
......@@ -202,6 +202,9 @@ several ways to match the message with the line (see the examples below):
202202* `~|`: Associates the error level and message with the *same* line as the
203203 *previous comment*. This is more convenient than using multiple carets when
204204 there are multiple messages associated with the same line.
205* `~v`: Associates the error level and message with the *next* error
206 annotation line. Each symbol (`v`) that you add adds a line to this, so `~vvv`
207 is three lines below the error annotation line.
205208* `~?`: Used to match error levels and messages with errors not having line
206209 information. These can be placed on any line in the test file, but are
207210 conventionally placed at the end.
......@@ -273,6 +276,18 @@ fn main() {
273276//~| ERROR this pattern has 1 field, but the corresponding tuple struct has 3 fields [E0023]
274277```
275278
279#### Positioned above error line
280
281Use the `//~v` idiom with number of v's in the string to indicate the number
282of lines below. This is typically used in lexer or parser tests matching on errors like unclosed
283delimiter or unclosed literal happening at the end of file.
284
285```rust,ignore
286// ignore-tidy-trailing-newlines
287//~v ERROR this file contains an unclosed delimiter
288fn main((ؼ
289```
290
276291#### Error without line information
277292
278293Use `//~?` to match an error without line information.
src/tools/compiletest/src/errors.rs+7-1
......@@ -122,13 +122,17 @@ fn parse_expected(
122122 // //~|
123123 // //~^
124124 // //~^^^^^
125 // //~v
126 // //~vvvvv
125127 // //~?
126128 // //[rev1]~
127129 // //[rev1,rev2]~^^
128130 static RE: OnceLock<Regex> = OnceLock::new();
129131
130132 let captures = RE
131 .get_or_init(|| Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||\^*)").unwrap())
133 .get_or_init(|| {
134 Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||[v\^]*)").unwrap()
135 })
132136 .captures(line)?;
133137
134138 match (test_revision, captures.name("revs")) {
......@@ -164,6 +168,8 @@ fn parse_expected(
164168 (true, Some(last_nonfollow_error.expect("encountered //~| without preceding //~^ line")))
165169 } else if line_num_adjust == "?" {
166170 (false, None)
171 } else if line_num_adjust.starts_with('v') {
172 (false, Some(line_num + line_num_adjust.len()))
167173 } else {
168174 (false, Some(line_num - line_num_adjust.len()))
169175 };
tests/ui/parser/issues/issue-103451.rs+1-1
......@@ -1,4 +1,4 @@
1//@ error-pattern: this file contains an unclosed delimiter
21struct R { }
2//~vv ERROR this file contains an unclosed delimiter
33struct S {
44 x: [u8; R
tests/ui/parser/issues/issue-10636-2.rs+1-1
......@@ -1,7 +1,7 @@
1//@ error-pattern: mismatched closing delimiter: `}`
21// FIXME(31528) we emit a bunch of silly errors here due to continuing past the
32// first one. This would be easy-ish to address by better recovery in tokenisation.
43
4//~vvvvv ERROR mismatched closing delimiter: `}`
55pub fn trace_option(option: Option<isize>) {
66 option.map(|some| 42;
77
tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs+1-2
......@@ -1,5 +1,4 @@
11// Fixed in #66054.
22// ignore-tidy-trailing-newlines
3//@ error-pattern: this file contains an unclosed delimiter
4//@ error-pattern: aborting due to 1 previous error
3//~v ERROR this file contains an unclosed delimiter
54#[Ѕ
\ No newline at end of file
tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4
2 --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
33 |
44LL | #[Ѕ
55 | - ^
tests/ui/parser/issues/issue-62524.rs+2-1
......@@ -1,6 +1,7 @@
11// ignore-tidy-trailing-newlines
2//@ error-pattern: aborting due to 1 previous error
2
33#![allow(uncommon_codepoints)]
44
5//~vv ERROR this file contains an unclosed delimiter
56y![
67Ϥ,
\ No newline at end of file
tests/ui/parser/issues/issue-62524.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/issue-62524.rs:6:3
2 --> $DIR/issue-62524.rs:7:3
33 |
44LL | y![
55 | - unclosed delimiter
tests/ui/parser/issues/issue-62554.rs+1-2
......@@ -1,5 +1,4 @@
1//@ error-pattern:this file contains an unclosed delimiter
2
31fn main() {}
42
3//~v ERROR this file contains an unclosed delimiter
54fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
tests/ui/parser/issues/issue-62554.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/issue-62554.rs:5:89
2 --> $DIR/issue-62554.rs:4:89
33 |
44LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
55 | - - - - -^
tests/ui/parser/issues/issue-62894.rs+1-1
......@@ -1,6 +1,6 @@
11// Regression test for #62894, shouldn't crash.
2//@ error-pattern: this file contains an unclosed delimiter
32
3//~vvv ERROR this file contains an unclosed delimiter
44fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
55
66fn main() {}
tests/ui/parser/issues/issue-62973.rs+3-1
......@@ -1,8 +1,10 @@
11// ignore-tidy-trailing-newlines
2//@ error-pattern: aborting due to 3 previous errors
32
43fn main() {}
54
5//~vvv ERROR mismatched closing delimiter: `)`
6//~vv ERROR mismatched closing delimiter: `)`
7//~vvv ERROR this file contains an unclosed delimiter
68fn p() { match s { v, E { [) {) }
79
810
tests/ui/parser/issues/issue-62973.stderr+3-3
......@@ -1,5 +1,5 @@
11error: mismatched closing delimiter: `)`
2 --> $DIR/issue-62973.rs:6:27
2 --> $DIR/issue-62973.rs:8:27
33 |
44LL | fn p() { match s { v, E { [) {) }
55 | ^^ mismatched closing delimiter
......@@ -7,7 +7,7 @@ LL | fn p() { match s { v, E { [) {) }
77 | unclosed delimiter
88
99error: mismatched closing delimiter: `)`
10 --> $DIR/issue-62973.rs:6:30
10 --> $DIR/issue-62973.rs:8:30
1111 |
1212LL | fn p() { match s { v, E { [) {) }
1313 | ^^ mismatched closing delimiter
......@@ -15,7 +15,7 @@ LL | fn p() { match s { v, E { [) {) }
1515 | unclosed delimiter
1616
1717error: this file contains an unclosed delimiter
18 --> $DIR/issue-62973.rs:8:2
18 --> $DIR/issue-62973.rs:10:2
1919 |
2020LL | fn p() { match s { v, E { [) {) }
2121 | - - - - missing open `(` for this delimiter
tests/ui/parser/issues/issue-63116.rs+2-1
......@@ -1,3 +1,4 @@
11// fixed by #66361
2//@ error-pattern: aborting due to 2 previous errors
2//~vv ERROR mismatched closing delimiter: `]`
3//~v ERROR this file contains an unclosed delimiter
34impl W <s(f;Y(;]
tests/ui/parser/issues/issue-63116.stderr+2-2
......@@ -1,5 +1,5 @@
11error: mismatched closing delimiter: `]`
2 --> $DIR/issue-63116.rs:3:14
2 --> $DIR/issue-63116.rs:4:14
33 |
44LL | impl W <s(f;Y(;]
55 | ^ ^ mismatched closing delimiter
......@@ -7,7 +7,7 @@ LL | impl W <s(f;Y(;]
77 | unclosed delimiter
88
99error: this file contains an unclosed delimiter
10 --> $DIR/issue-63116.rs:3:18
10 --> $DIR/issue-63116.rs:4:18
1111 |
1212LL | impl W <s(f;Y(;]
1313 | - -^
tests/ui/parser/issues/issue-63135.rs+1-2
......@@ -1,3 +1,2 @@
1//@ error-pattern: this file contains an unclosed delimiter
2//@ error-pattern: aborting due to 1 previous error
1//~v ERROR this file contains an unclosed delimiter
32fn i(n{...,f #
tests/ui/parser/issues/issue-63135.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/issue-63135.rs:3:16
2 --> $DIR/issue-63135.rs:2:16
33 |
44LL | fn i(n{...,f #
55 | - - ^
tests/ui/parser/issues/issue-81804.rs+2-3
......@@ -1,6 +1,5 @@
1//@ error-pattern: this file contains an unclosed delimiter
2//@ error-pattern: this file contains an unclosed delimiter
3
41fn main() {}
52
3//~vv ERROR mismatched closing delimiter: `}`
4//~v ERROR this file contains an unclosed delimiter
65fn p([=(}
tests/ui/parser/issues/issue-81804.stderr+2-2
......@@ -1,5 +1,5 @@
11error: mismatched closing delimiter: `}`
2 --> $DIR/issue-81804.rs:6:8
2 --> $DIR/issue-81804.rs:5:8
33 |
44LL | fn p([=(}
55 | ^^ mismatched closing delimiter
......@@ -7,7 +7,7 @@ LL | fn p([=(}
77 | unclosed delimiter
88
99error: this file contains an unclosed delimiter
10 --> $DIR/issue-81804.rs:6:11
10 --> $DIR/issue-81804.rs:5:11
1111 |
1212LL | fn p([=(}
1313 | -- ^
tests/ui/parser/issues/issue-81827.rs+2-5
......@@ -1,10 +1,7 @@
1//@ error-pattern: this file contains an unclosed delimiter
2//@ error-pattern: mismatched closing delimiter: `]`
3
41#![crate_name="0"]
52
6
7
83fn main() {}
94
5//~vv ERROR mismatched closing delimiter: `]`
6//~v ERROR this file contains an unclosed delimiter
107fn r()->i{0|{#[cfg(r(0{]0
tests/ui/parser/issues/issue-81827.stderr+2-2
......@@ -1,5 +1,5 @@
11error: mismatched closing delimiter: `]`
2 --> $DIR/issue-81827.rs:10:23
2 --> $DIR/issue-81827.rs:7:23
33 |
44LL | fn r()->i{0|{#[cfg(r(0{]0
55 | - ^^ mismatched closing delimiter
......@@ -8,7 +8,7 @@ LL | fn r()->i{0|{#[cfg(r(0{]0
88 | closing delimiter possibly meant for this
99
1010error: this file contains an unclosed delimiter
11 --> $DIR/issue-81827.rs:10:27
11 --> $DIR/issue-81827.rs:7:27
1212 |
1313LL | fn r()->i{0|{#[cfg(r(0{]0
1414 | - - - ^
tests/ui/parser/issues/issue-84104.rs+1-1
......@@ -1,2 +1,2 @@
1//@ error-pattern: this file contains an unclosed delimiter
1//~v ERROR this file contains an unclosed delimiter
22#[i=i::<ښܖ<
tests/ui/parser/issues/issue-84148-2.rs+1-1
......@@ -1,2 +1,2 @@
1//@ error-pattern: this file contains an unclosed delimiter
1//~v ERROR this file contains an unclosed delimiter
22fn f(t:for<>t?
tests/ui/parser/issues/issue-88770.rs+1-2
......@@ -1,7 +1,6 @@
11// Regression test for the ICE described in #88770.
22
3//@ error-pattern:this file contains an unclosed delimiter
4
3//~vvvv ERROR this file contains an unclosed delimiter
54fn m(){print!("",(c for&g
65u
76e
tests/ui/parser/issues/issue-88770.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/issue-88770.rs:8:3
2 --> $DIR/issue-88770.rs:7:3
33 |
44LL | fn m(){print!("",(c for&g
55 | - - - unclosed delimiter
tests/ui/parser/mbe_missing_right_paren.rs+1-1
......@@ -1,3 +1,3 @@
11// ignore-tidy-trailing-newlines
2//@ error-pattern: this file contains an unclosed delimiter
2//~v ERROR this file contains an unclosed delimiter
33macro_rules! abc(ؼ
\ No newline at end of file
tests/ui/parser/missing_right_paren.rs+1-2
......@@ -1,4 +1,3 @@
11// ignore-tidy-trailing-newlines
2//@ error-pattern: this file contains an unclosed delimiter
3//@ error-pattern: aborting due to 1 previous error
2//~v ERROR this file contains an unclosed delimiter
43fn main((ؼ
\ No newline at end of file
tests/ui/parser/missing_right_paren.stderr+1-1
......@@ -1,5 +1,5 @@
11error: this file contains an unclosed delimiter
2 --> $DIR/missing_right_paren.rs:4:11
2 --> $DIR/missing_right_paren.rs:3:11
33 |
44LL | fn main((ؼ
55 | -- ^
tests/ui/parser/unbalanced-doublequote.rs+1-3
......@@ -1,6 +1,4 @@
1//@ error-pattern: unterminated double quote string
2
3
1//~vv ERROR unterminated double quote string
42fn main() {
53 "
64}
tests/ui/parser/unbalanced-doublequote.stderr+1-1
......@@ -1,5 +1,5 @@
11error[E0765]: unterminated double quote string
2 --> $DIR/unbalanced-doublequote.rs:5:5
2 --> $DIR/unbalanced-doublequote.rs:3:5
33 |
44LL | / "
55LL | | }
tests/ui/parser/use-unclosed-brace.rs+1-1
......@@ -1,4 +1,3 @@
1//@ error-pattern: this file contains an unclosed delimiter
21use foo::{bar, baz;
32
43use std::fmt::Display;
......@@ -7,4 +6,5 @@ mod bar { }
76
87mod baz { }
98
9//~v ERROR this file contains an unclosed delimiter
1010fn main() {}