Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1ae22d8
Implement `Debug` for `EncodeWide`
thaliaarchi Apr 22, 2025
82d9758
test: make sure `fmt-write-bloat` does not vacuously pass
jieyouxu Oct 4, 2025
1dd0a01
Fix backtraces with -C panic=abort on qnx; emit unwind tables by default
Hoverbear Oct 7, 2025
1e6b444
library: fs: Factor out a `file_time_to_timespec` function in prepara…
joshtriplett Oct 7, 2025
1bf555c
library: fs: Factor out the Apple file time to attrlist code for reuse
joshtriplett Oct 7, 2025
0e2130c
std::thread spawn: Docs: Link to Builder::spawn; Make same.
evanj Oct 8, 2025
7225454
Implement fs api set_times and set_times_nofollow
chenyukang Oct 8, 2025
3d40fa6
Update library/std/src/fs.rs
chenyukang Oct 9, 2025
6308e76
Update library/std/src/fs.rs
chenyukang Oct 9, 2025
1c5c8ca
use proper unsupported
chenyukang Oct 9, 2025
46c6f0a
rebase #147504
chenyukang Oct 9, 2025
2438df7
support fs::set_times for wasi
chenyukang Oct 9, 2025
1dd5641
add doc alias for set_times_nofollow
chenyukang Oct 9, 2025
6fd1c2b
add doc alias for set_times
chenyukang Oct 9, 2025
901366a
fix c_char error in Android
chenyukang Oct 9, 2025
f8118d8
unsupported: Use `unsupported()` for `set_times`
joshtriplett Oct 9, 2025
d2f590a
unsupported: Use `unsupported()` for `set_times_nofollow`
joshtriplett Oct 9, 2025
8182085
Fix compiling error for redox etc
chenyukang Oct 15, 2025
c4dc39b
add link to Builder (code review improvement)
evanj Oct 16, 2025
10a5334
bootstrap: migrate to object 0.37
durin42 Jun 17, 2025
fcc47d0
rustdoc: Fix passes order so intra-doc links are collected after stri…
GuillaumeGomez Oct 17, 2025
e67d502
Fix autodiff incorrectly applying fat-lto to proc-macro crates
osamakader Oct 16, 2025
b3bb750
Add regression tests for intra-doc links
GuillaumeGomez Oct 17, 2025
211fdcc
Rollup merge of #140153 - thaliaarchi:encode-wide-debug, r=ChrisDenton
GuillaumeGomez Oct 17, 2025
2edc503
Rollup merge of #143669 - jieyouxu:fmt-write-bloat, r=ChrisDenton
GuillaumeGomez Oct 17, 2025
b7cd5ea
Rollup merge of #147454 - ferrocene:hoverbear/panic-abort-uwtables-qn…
GuillaumeGomez Oct 17, 2025
5933e5c
Rollup merge of #147468 - chenyukang:yukang-api-set-times, r=joshtrip…
GuillaumeGomez Oct 17, 2025
8faaeca
Rollup merge of #147494 - evanj:evan.jones/thread-spawn-link, r=joboet
GuillaumeGomez Oct 17, 2025
344eb54
Rollup merge of #147783 - durin42:object-unification, r=Zalathar
GuillaumeGomez Oct 17, 2025
9e7909a
Rollup merge of #147792 - osamakader:fix-autodiff-proc-macro-lto, r=p…
GuillaumeGomez Oct 17, 2025
79a8db5
Rollup merge of #147809 - GuillaumeGomez:fix-rustdoc-passes, r=fmease
GuillaumeGomez Oct 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,8 @@ impl Session {
// Autodiff currently requires fat-lto to have access to the llvm-ir of all (indirectly) used functions and types.
// fat-lto is the easiest solution to this requirement, but quite expensive.
// FIXME(autodiff): Make autodiff also work with embed-bc instead of fat-lto.
if self.opts.autodiff_enabled() {
// Don't apply fat-lto to proc-macro crates as they cannot use fat-lto without -Zdylib-lto
if self.opts.autodiff_enabled() && !self.opts.crate_types.contains(&CrateType::ProcMacro) {
return config::Lto::Fat;
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_target/src/spec/base/nto_qnx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ pub(crate) fn opts() -> TargetOptions {
has_thread_local: false,
linker: Some("qcc".into()),
os: "nto".into(),
// We want backtraces to work by default and they rely on unwind tables
// (regardless of `-C panic` strategy).
default_uwtable: true,
position_independent_executables: true,
static_position_independent_executables: true,
relro_level: RelroLevel::Full,
Expand Down
11 changes: 11 additions & 0 deletions library/alloc/src/wtf8/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,17 @@ fn wtf8_encode_wide_size_hint() {
assert!(iter.next().is_none());
}

#[test]
fn wtf8_encode_wide_debug() {
let mut string = Wtf8Buf::from_str("aé ");
string.push(CodePoint::from_u32(0xD83D).unwrap());
string.push_char('💩');
assert_eq!(
format!("{:?}", string.encode_wide()),
r#"EncodeWide(['a', 'é', ' ', 0xD83D, 0xD83D, 0xDCA9])"#
);
}

#[test]
fn wtf8_clone_into() {
let mut string = Wtf8Buf::new();
Expand Down
29 changes: 25 additions & 4 deletions library/core/src/wtf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,15 +562,36 @@ impl Iterator for EncodeWide<'_> {
}
}

#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
impl FusedIterator for EncodeWide<'_> {}

#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
impl fmt::Debug for EncodeWide<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EncodeWide").finish_non_exhaustive()
struct CodeUnit(u16);
impl fmt::Debug for CodeUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// This output attempts to balance readability with precision.
// Render characters which take only one WTF-16 code unit using
// `char` syntax and everything else as code units with hex
// integer syntax (including paired and unpaired surrogate
// halves). Since Rust has no `char`-like type for WTF-16, this
// isn't perfect, so if this output isn't suitable, it is open
// to being changed (see #140153).
match char::from_u32(self.0 as u32) {
Some(c) => write!(f, "{c:?}"),
None => write!(f, "0x{:04X}", self.0),
}
}
}

write!(f, "EncodeWide(")?;
f.debug_list().entries(self.clone().map(CodeUnit)).finish()?;
write!(f, ")")?;
Ok(())
}
}

#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
impl FusedIterator for EncodeWide<'_> {}

impl Hash for CodePoint {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
Expand Down
81 changes: 81 additions & 0 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,87 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result
inner(path.as_ref(), contents.as_ref())
}

/// Changes the timestamps of the file or directory at the specified path.
///
/// This function will attempt to set the access and modification times
/// to the times specified. If the path refers to a symbolic link, this function
/// will follow the link and change the timestamps of the target file.
///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `utimensat` function on Unix platforms, the
/// `setattrlist` function on Apple platforms, and the `SetFileTime` function on Windows.
///
/// # Errors
///
/// This function will return an error if the user lacks permission to change timestamps on the
/// target file or symlink. It may also return an error if the OS does not support it.
///
/// # Examples
///
/// ```no_run
/// #![feature(fs_set_times)]
/// use std::fs::{self, FileTimes};
/// use std::time::SystemTime;
///
/// fn main() -> std::io::Result<()> {
/// let now = SystemTime::now();
/// let times = FileTimes::new()
/// .set_accessed(now)
/// .set_modified(now);
/// fs::set_times("foo.txt", times)?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "fs_set_times", issue = "147455")]
#[doc(alias = "utimens")]
#[doc(alias = "utimes")]
#[doc(alias = "utime")]
pub fn set_times<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {
fs_imp::set_times(path.as_ref(), times.0)
}

/// Changes the timestamps of the file or symlink at the specified path.
///
/// This function will attempt to set the access and modification times
/// to the times specified. Differ from `set_times`, if the path refers to a symbolic link,
/// this function will change the timestamps of the symlink itself, not the target file.
///
/// # Platform-specific behavior
///
/// This function currently corresponds to the `utimensat` function with `AT_SYMLINK_NOFOLLOW` on
/// Unix platforms, the `setattrlist` function with `FSOPT_NOFOLLOW` on Apple platforms, and the
/// `SetFileTime` function on Windows.
///
/// # Errors
///
/// This function will return an error if the user lacks permission to change timestamps on the
/// target file or symlink. It may also return an error if the OS does not support it.
///
/// # Examples
///
/// ```no_run
/// #![feature(fs_set_times)]
/// use std::fs::{self, FileTimes};
/// use std::time::SystemTime;
///
/// fn main() -> std::io::Result<()> {
/// let now = SystemTime::now();
/// let times = FileTimes::new()
/// .set_accessed(now)
/// .set_modified(now);
/// fs::set_times_nofollow("symlink.txt", times)?;
/// Ok(())
/// }
/// ```
#[unstable(feature = "fs_set_times", issue = "147455")]
#[doc(alias = "utimensat")]
#[doc(alias = "lutimens")]
#[doc(alias = "lutimes")]
pub fn set_times_nofollow<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {
fs_imp::set_times_nofollow(path.as_ref(), times.0)
}

#[stable(feature = "file_lock", since = "1.89.0")]
impl error::Error for TryLockError {}

Expand Down
219 changes: 219 additions & 0 deletions library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2226,3 +2226,222 @@ fn test_open_options_invalid_combinations() {
assert_eq!(err.kind(), ErrorKind::InvalidInput);
assert_eq!(err.to_string(), "must specify at least one of read, write, or append access");
}

#[test]
fn test_fs_set_times() {
#[cfg(target_vendor = "apple")]
use crate::os::darwin::fs::FileTimesExt;
#[cfg(windows)]
use crate::os::windows::fs::FileTimesExt;

let tmp = tmpdir();
let path = tmp.join("foo");
File::create(&path).unwrap();

let mut times = FileTimes::new();
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
times = times.set_accessed(accessed).set_modified(modified);

#[cfg(any(windows, target_vendor = "apple"))]
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
#[cfg(any(windows, target_vendor = "apple"))]
{
times = times.set_created(created);
}

match fs::set_times(&path, times) {
// Allow unsupported errors on platforms which don't support setting times.
#[cfg(not(any(
windows,
all(
unix,
not(any(
target_os = "android",
target_os = "redox",
target_os = "espidf",
target_os = "horizon"
))
)
)))]
Err(e) if e.kind() == ErrorKind::Unsupported => return,
Err(e) => panic!("error setting file times: {e:?}"),
Ok(_) => {}
}

let metadata = fs::metadata(&path).unwrap();
assert_eq!(metadata.accessed().unwrap(), accessed);
assert_eq!(metadata.modified().unwrap(), modified);
#[cfg(any(windows, target_vendor = "apple"))]
{
assert_eq!(metadata.created().unwrap(), created);
}
}

#[test]
fn test_fs_set_times_follows_symlink() {
#[cfg(target_vendor = "apple")]
use crate::os::darwin::fs::FileTimesExt;
#[cfg(windows)]
use crate::os::windows::fs::FileTimesExt;

let tmp = tmpdir();

// Create a target file
let target = tmp.join("target");
File::create(&target).unwrap();

// Create a symlink to the target
#[cfg(unix)]
let link = tmp.join("link");
#[cfg(unix)]
crate::os::unix::fs::symlink(&target, &link).unwrap();

#[cfg(windows)]
let link = tmp.join("link.txt");
#[cfg(windows)]
crate::os::windows::fs::symlink_file(&target, &link).unwrap();

// Get the symlink's own modified time BEFORE calling set_times (to compare later)
// We don't check accessed time because reading metadata may update atime on some platforms.
let link_metadata_before = fs::symlink_metadata(&link).unwrap();
let link_modified_before = link_metadata_before.modified().unwrap();

let mut times = FileTimes::new();
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
times = times.set_accessed(accessed).set_modified(modified);

#[cfg(any(windows, target_vendor = "apple"))]
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
#[cfg(any(windows, target_vendor = "apple"))]
{
times = times.set_created(created);
}

// Call fs::set_times on the symlink - it should follow the link and modify the target
match fs::set_times(&link, times) {
// Allow unsupported errors on platforms which don't support setting times.
#[cfg(not(any(
windows,
all(
unix,
not(any(
target_os = "android",
target_os = "redox",
target_os = "espidf",
target_os = "horizon"
))
)
)))]
Err(e) if e.kind() == ErrorKind::Unsupported => return,
Err(e) => panic!("error setting file times through symlink: {e:?}"),
Ok(_) => {}
}

// Verify that the TARGET file's times were changed (following the symlink)
let target_metadata = fs::metadata(&target).unwrap();
assert_eq!(
target_metadata.accessed().unwrap(),
accessed,
"target file accessed time should match"
);
assert_eq!(
target_metadata.modified().unwrap(),
modified,
"target file modified time should match"
);
#[cfg(any(windows, target_vendor = "apple"))]
{
assert_eq!(
target_metadata.created().unwrap(),
created,
"target file created time should match"
);
}

// Also verify through the symlink (fs::metadata follows symlinks)
let link_followed_metadata = fs::metadata(&link).unwrap();
assert_eq!(link_followed_metadata.accessed().unwrap(), accessed);
assert_eq!(link_followed_metadata.modified().unwrap(), modified);

// Verify that the SYMLINK ITSELF was NOT modified
// Note: We only check modified time, not accessed time, because reading the symlink
// metadata may update its atime on some platforms (e.g., Linux).
let link_metadata_after = fs::symlink_metadata(&link).unwrap();
assert_eq!(
link_metadata_after.modified().unwrap(),
link_modified_before,
"symlink's own modified time should not change"
);
}

#[test]
fn test_fs_set_times_nofollow() {
#[cfg(target_vendor = "apple")]
use crate::os::darwin::fs::FileTimesExt;
#[cfg(windows)]
use crate::os::windows::fs::FileTimesExt;

let tmp = tmpdir();

// Create a target file and a symlink to it
let target = tmp.join("target");
File::create(&target).unwrap();

#[cfg(unix)]
let link = tmp.join("link");
#[cfg(unix)]
crate::os::unix::fs::symlink(&target, &link).unwrap();

#[cfg(windows)]
let link = tmp.join("link.txt");
#[cfg(windows)]
crate::os::windows::fs::symlink_file(&target, &link).unwrap();

let mut times = FileTimes::new();
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(11111);
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(22222);
times = times.set_accessed(accessed).set_modified(modified);

#[cfg(any(windows, target_vendor = "apple"))]
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(33333);
#[cfg(any(windows, target_vendor = "apple"))]
{
times = times.set_created(created);
}

// Set times on the symlink itself (not following it)
match fs::set_times_nofollow(&link, times) {
// Allow unsupported errors on platforms which don't support setting times.
#[cfg(not(any(
windows,
all(
unix,
not(any(
target_os = "android",
target_os = "redox",
target_os = "espidf",
target_os = "horizon"
))
)
)))]
Err(e) if e.kind() == ErrorKind::Unsupported => return,
Err(e) => panic!("error setting symlink times: {e:?}"),
Ok(_) => {}
}

// Read symlink metadata (without following)
let metadata = fs::symlink_metadata(&link).unwrap();
assert_eq!(metadata.accessed().unwrap(), accessed);
assert_eq!(metadata.modified().unwrap(), modified);
#[cfg(any(windows, target_vendor = "apple"))]
{
assert_eq!(metadata.created().unwrap(), created);
}

// Verify that the target file's times were NOT changed
let target_metadata = fs::metadata(&target).unwrap();
assert_ne!(target_metadata.accessed().unwrap(), accessed);
assert_ne!(target_metadata.modified().unwrap(), modified);
}
Loading
Loading