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
This commit is contained in:
commit
2196affd01
43 changed files with 274 additions and 183 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -495,7 +495,7 @@ impl<T> Cell<T> {
|
|||
/// ```
|
||||
#[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<T: Copy> Cell<T> {
|
|||
/// ```
|
||||
#[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<T: ?Sized> Cell<T> {
|
|||
/// ```
|
||||
#[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<T: ?Sized> Cell<T> {
|
|||
/// ```
|
||||
#[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<T> {
|
||||
// SAFETY: `&mut` ensures unique access.
|
||||
unsafe { &*(t as *mut T as *const Cell<T>) }
|
||||
|
@ -695,7 +695,7 @@ impl<T> 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<T>] {
|
||||
// SAFETY: `Cell<T>` has the same memory layout as `T`.
|
||||
unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
|
||||
|
|
|
@ -2370,7 +2370,7 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
|
|||
#[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove_file<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
|||
#[doc(alias = "stat")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
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<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
|||
#[doc(alias = "lstat")]
|
||||
#[stable(feature = "symlink_metadata", since = "1.1.0")]
|
||||
pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
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<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
|
|||
#[doc(alias = "CreateHardLink", alias = "linkat")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(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<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Re
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
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<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
|||
#[doc(alias = "rmdir", alias = "RemoveDirectory")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove_dir<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
|||
#[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
|
||||
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<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
|
|||
#[doc(alias = "chmod", alias = "SetFileAttributes")]
|
||||
#[stable(feature = "set_permissions", since = "1.1.0")]
|
||||
pub fn set_permissions<P: AsRef<Path>>(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 {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
|
||||
f(path)
|
||||
}
|
||||
|
||||
pub use imp::{
|
||||
DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
|
||||
ReadDir,
|
||||
};
|
||||
|
||||
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
|
||||
// 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<PathBuf> {
|
||||
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<FileAttr> {
|
||||
with_native_path(path, &imp::stat)
|
||||
}
|
||||
|
||||
pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
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<PathBuf> {
|
||||
with_native_path(path, &imp::canonicalize)
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
// FIXME: use with_native_path
|
||||
imp::copy(from, to)
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
// FIXME: use with_native_path
|
||||
imp::exists(path)
|
||||
}
|
||||
|
|
|
@ -926,7 +926,7 @@ impl DirEntry {
|
|||
miri
|
||||
))]
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
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<PathBuf> {
|
||||
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<ReadDir> {
|
|||
}
|
||||
}
|
||||
|
||||
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<PathBuf> {
|
||||
run_path_with_cstr(p, &|c_path| {
|
||||
let p = c_path.as_ptr();
|
||||
pub fn readlink(c_path: &CStr) -> io::Result<PathBuf> {
|
||||
let p = c_path.as_ptr();
|
||||
|
||||
let mut buf = Vec::with_capacity(256);
|
||||
let mut buf = Vec::with_capacity(256);
|
||||
|
||||
loop {
|
||||
let buf_read =
|
||||
cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })?
|
||||
as usize;
|
||||
loop {
|
||||
let buf_read =
|
||||
cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
|
||||
|
||||
unsafe {
|
||||
buf.set_len(buf_read);
|
||||
}
|
||||
|
||||
if buf_read != buf.capacity() {
|
||||
buf.shrink_to_fit();
|
||||
|
||||
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 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 stat(p: &Path) -> io::Result<FileAttr> {
|
||||
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;
|
||||
}
|
||||
unsafe {
|
||||
buf.set_len(buf_read);
|
||||
}
|
||||
|
||||
let mut stat: stat64 = unsafe { mem::zeroed() };
|
||||
cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
|
||||
Ok(FileAttr::from_stat64(stat))
|
||||
})
|
||||
}
|
||||
if buf_read != buf.capacity() {
|
||||
buf.shrink_to_fit();
|
||||
|
||||
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
||||
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;
|
||||
}
|
||||
return Ok(PathBuf::from(OsString::from_vec(buf)));
|
||||
}
|
||||
|
||||
let mut stat: stat64 = unsafe { mem::zeroed() };
|
||||
cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
|
||||
Ok(FileAttr::from_stat64(stat))
|
||||
})
|
||||
// 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 canonicalize(p: &Path) -> io::Result<PathBuf> {
|
||||
let r = run_path_with_cstr(p, &|path| unsafe {
|
||||
Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
|
||||
})?;
|
||||
pub fn symlink(original: &CStr, link: &CStr) -> io::Result<()> {
|
||||
cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
|
||||
}
|
||||
|
||||
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: &CStr) -> io::Result<FileAttr> {
|
||||
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))
|
||||
}
|
||||
|
||||
pub fn lstat(p: &CStr) -> io::Result<FileAttr> {
|
||||
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))
|
||||
}
|
||||
|
||||
pub fn canonicalize(path: &CStr) -> io::Result<PathBuf> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -122,13 +122,17 @@ fn parse_expected(
|
|||
// //~|
|
||||
// //~^
|
||||
// //~^^^^^
|
||||
// //~v
|
||||
// //~vvvvv
|
||||
// //~?
|
||||
// //[rev1]~
|
||||
// //[rev1,rev2]~^^
|
||||
static RE: OnceLock<Regex> = OnceLock::new();
|
||||
|
||||
let captures = RE
|
||||
.get_or_init(|| Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||\^*)").unwrap())
|
||||
.get_or_init(|| {
|
||||
Regex::new(r"//(?:\[(?P<revs>[\w\-,]+)])?~(?P<adjust>\?|\||[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()))
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<isize>) {
|
||||
option.map(|some| 42;
|
||||
|
||||
|
|
|
@ -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
|
||||
#[Ѕ
|
|
@ -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 | #[Ѕ
|
||||
| - ^
|
||||
|
|
|
@ -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![
|
||||
Ϥ,
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
| - - - - -^
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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 { [) {) }
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <s(f;Y(;]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: mismatched closing delimiter: `]`
|
||||
--> $DIR/issue-63116.rs:3:14
|
||||
--> $DIR/issue-63116.rs:4:14
|
||||
|
|
||||
LL | impl W <s(f;Y(;]
|
||||
| ^ ^ mismatched closing delimiter
|
||||
|
@ -7,7 +7,7 @@ LL | impl W <s(f;Y(;]
|
|||
| unclosed delimiter
|
||||
|
||||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-63116.rs:3:18
|
||||
--> $DIR/issue-63116.rs:4:18
|
||||
|
|
||||
LL | impl W <s(f;Y(;]
|
||||
| - -^
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
//@ 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 i(n{...,f #
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: this file contains an unclosed delimiter
|
||||
--> $DIR/issue-63135.rs:3:16
|
||||
--> $DIR/issue-63135.rs:2:16
|
||||
|
|
||||
LL | fn i(n{...,f #
|
||||
| - - ^
|
||||
|
|
|
@ -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([=(}
|
||||
|
|
|
@ -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([=(}
|
||||
| -- ^
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
| - - - ^
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
//@ error-pattern: this file contains an unclosed delimiter
|
||||
//~v ERROR this file contains an unclosed delimiter
|
||||
#[i=i::<ښܖ<
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(ؼ
|
|
@ -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((ؼ
|
|
@ -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((ؼ
|
||||
| -- ^
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
//@ error-pattern: unterminated double quote string
|
||||
|
||||
|
||||
//~vv ERROR unterminated double quote string
|
||||
fn main() {
|
||||
"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0765]: unterminated double quote string
|
||||
--> $DIR/unbalanced-doublequote.rs:5:5
|
||||
--> $DIR/unbalanced-doublequote.rs:3:5
|
||||
|
|
||||
LL | / "
|
||||
LL | | }
|
||||
|
|
|
@ -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() {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue