Skip to content

Commit 2593d24

Browse files
committed
Auto merge of #147822 - GuillaumeGomez:rollup-338omm1, r=GuillaumeGomez
Rollup of 7 pull requests Successful merges: - #140153 (Implement `Debug` for `EncodeWide`) - #147454 (Fix backtraces with `-C panic=abort` on qnx; emit unwind tables by default) - #147468 (Implement fs api set_times and set_times_nofollow) - #147494 (std::thread spawn: Docs: Link to Builder::spawn; Make same.) - #147783 (bootstrap: migrate to object 0.37) - #147792 (Fix autodiff incorrectly applying fat-lto to proc-macro crates ) - #147809 (rustdoc: Fix passes order so intra-doc links are collected after stripping passes) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f464759 + 3e92c2d commit 2593d24

File tree

26 files changed

+667
-69
lines changed

26 files changed

+667
-69
lines changed

compiler/rustc_session/src/session.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,8 @@ impl Session {
603603
// Autodiff currently requires fat-lto to have access to the llvm-ir of all (indirectly) used functions and types.
604604
// fat-lto is the easiest solution to this requirement, but quite expensive.
605605
// FIXME(autodiff): Make autodiff also work with embed-bc instead of fat-lto.
606-
if self.opts.autodiff_enabled() {
606+
// Don't apply fat-lto to proc-macro crates as they cannot use fat-lto without -Zdylib-lto
607+
if self.opts.autodiff_enabled() && !self.opts.crate_types.contains(&CrateType::ProcMacro) {
607608
return config::Lto::Fat;
608609
}
609610

compiler/rustc_target/src/spec/base/nto_qnx.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ pub(crate) fn opts() -> TargetOptions {
1212
has_thread_local: false,
1313
linker: Some("qcc".into()),
1414
os: "nto".into(),
15+
// We want backtraces to work by default and they rely on unwind tables
16+
// (regardless of `-C panic` strategy).
17+
default_uwtable: true,
1518
position_independent_executables: true,
1619
static_position_independent_executables: true,
1720
relro_level: RelroLevel::Full,

library/alloc/src/wtf8/tests.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,17 @@ fn wtf8_encode_wide_size_hint() {
579579
assert!(iter.next().is_none());
580580
}
581581

582+
#[test]
583+
fn wtf8_encode_wide_debug() {
584+
let mut string = Wtf8Buf::from_str("aé ");
585+
string.push(CodePoint::from_u32(0xD83D).unwrap());
586+
string.push_char('💩');
587+
assert_eq!(
588+
format!("{:?}", string.encode_wide()),
589+
r#"EncodeWide(['a', 'é', ' ', 0xD83D, 0xD83D, 0xDCA9])"#
590+
);
591+
}
592+
582593
#[test]
583594
fn wtf8_clone_into() {
584595
let mut string = Wtf8Buf::new();

library/core/src/wtf8.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,36 @@ impl Iterator for EncodeWide<'_> {
562562
}
563563
}
564564

565+
#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
566+
impl FusedIterator for EncodeWide<'_> {}
567+
568+
#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
565569
impl fmt::Debug for EncodeWide<'_> {
566570
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567-
f.debug_struct("EncodeWide").finish_non_exhaustive()
571+
struct CodeUnit(u16);
572+
impl fmt::Debug for CodeUnit {
573+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
574+
// This output attempts to balance readability with precision.
575+
// Render characters which take only one WTF-16 code unit using
576+
// `char` syntax and everything else as code units with hex
577+
// integer syntax (including paired and unpaired surrogate
578+
// halves). Since Rust has no `char`-like type for WTF-16, this
579+
// isn't perfect, so if this output isn't suitable, it is open
580+
// to being changed (see #140153).
581+
match char::from_u32(self.0 as u32) {
582+
Some(c) => write!(f, "{c:?}"),
583+
None => write!(f, "0x{:04X}", self.0),
584+
}
585+
}
586+
}
587+
588+
write!(f, "EncodeWide(")?;
589+
f.debug_list().entries(self.clone().map(CodeUnit)).finish()?;
590+
write!(f, ")")?;
591+
Ok(())
568592
}
569593
}
570594

571-
#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
572-
impl FusedIterator for EncodeWide<'_> {}
573-
574595
impl Hash for CodePoint {
575596
#[inline]
576597
fn hash<H: Hasher>(&self, state: &mut H) {

library/std/src/fs.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,87 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result
387387
inner(path.as_ref(), contents.as_ref())
388388
}
389389

390+
/// Changes the timestamps of the file or directory at the specified path.
391+
///
392+
/// This function will attempt to set the access and modification times
393+
/// to the times specified. If the path refers to a symbolic link, this function
394+
/// will follow the link and change the timestamps of the target file.
395+
///
396+
/// # Platform-specific behavior
397+
///
398+
/// This function currently corresponds to the `utimensat` function on Unix platforms, the
399+
/// `setattrlist` function on Apple platforms, and the `SetFileTime` function on Windows.
400+
///
401+
/// # Errors
402+
///
403+
/// This function will return an error if the user lacks permission to change timestamps on the
404+
/// target file or symlink. It may also return an error if the OS does not support it.
405+
///
406+
/// # Examples
407+
///
408+
/// ```no_run
409+
/// #![feature(fs_set_times)]
410+
/// use std::fs::{self, FileTimes};
411+
/// use std::time::SystemTime;
412+
///
413+
/// fn main() -> std::io::Result<()> {
414+
/// let now = SystemTime::now();
415+
/// let times = FileTimes::new()
416+
/// .set_accessed(now)
417+
/// .set_modified(now);
418+
/// fs::set_times("foo.txt", times)?;
419+
/// Ok(())
420+
/// }
421+
/// ```
422+
#[unstable(feature = "fs_set_times", issue = "147455")]
423+
#[doc(alias = "utimens")]
424+
#[doc(alias = "utimes")]
425+
#[doc(alias = "utime")]
426+
pub fn set_times<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {
427+
fs_imp::set_times(path.as_ref(), times.0)
428+
}
429+
430+
/// Changes the timestamps of the file or symlink at the specified path.
431+
///
432+
/// This function will attempt to set the access and modification times
433+
/// to the times specified. Differ from `set_times`, if the path refers to a symbolic link,
434+
/// this function will change the timestamps of the symlink itself, not the target file.
435+
///
436+
/// # Platform-specific behavior
437+
///
438+
/// This function currently corresponds to the `utimensat` function with `AT_SYMLINK_NOFOLLOW` on
439+
/// Unix platforms, the `setattrlist` function with `FSOPT_NOFOLLOW` on Apple platforms, and the
440+
/// `SetFileTime` function on Windows.
441+
///
442+
/// # Errors
443+
///
444+
/// This function will return an error if the user lacks permission to change timestamps on the
445+
/// target file or symlink. It may also return an error if the OS does not support it.
446+
///
447+
/// # Examples
448+
///
449+
/// ```no_run
450+
/// #![feature(fs_set_times)]
451+
/// use std::fs::{self, FileTimes};
452+
/// use std::time::SystemTime;
453+
///
454+
/// fn main() -> std::io::Result<()> {
455+
/// let now = SystemTime::now();
456+
/// let times = FileTimes::new()
457+
/// .set_accessed(now)
458+
/// .set_modified(now);
459+
/// fs::set_times_nofollow("symlink.txt", times)?;
460+
/// Ok(())
461+
/// }
462+
/// ```
463+
#[unstable(feature = "fs_set_times", issue = "147455")]
464+
#[doc(alias = "utimensat")]
465+
#[doc(alias = "lutimens")]
466+
#[doc(alias = "lutimes")]
467+
pub fn set_times_nofollow<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {
468+
fs_imp::set_times_nofollow(path.as_ref(), times.0)
469+
}
470+
390471
#[stable(feature = "file_lock", since = "1.89.0")]
391472
impl error::Error for TryLockError {}
392473

library/std/src/fs/tests.rs

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,3 +2226,222 @@ fn test_open_options_invalid_combinations() {
22262226
assert_eq!(err.kind(), ErrorKind::InvalidInput);
22272227
assert_eq!(err.to_string(), "must specify at least one of read, write, or append access");
22282228
}
2229+
2230+
#[test]
2231+
fn test_fs_set_times() {
2232+
#[cfg(target_vendor = "apple")]
2233+
use crate::os::darwin::fs::FileTimesExt;
2234+
#[cfg(windows)]
2235+
use crate::os::windows::fs::FileTimesExt;
2236+
2237+
let tmp = tmpdir();
2238+
let path = tmp.join("foo");
2239+
File::create(&path).unwrap();
2240+
2241+
let mut times = FileTimes::new();
2242+
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
2243+
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
2244+
times = times.set_accessed(accessed).set_modified(modified);
2245+
2246+
#[cfg(any(windows, target_vendor = "apple"))]
2247+
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
2248+
#[cfg(any(windows, target_vendor = "apple"))]
2249+
{
2250+
times = times.set_created(created);
2251+
}
2252+
2253+
match fs::set_times(&path, times) {
2254+
// Allow unsupported errors on platforms which don't support setting times.
2255+
#[cfg(not(any(
2256+
windows,
2257+
all(
2258+
unix,
2259+
not(any(
2260+
target_os = "android",
2261+
target_os = "redox",
2262+
target_os = "espidf",
2263+
target_os = "horizon"
2264+
))
2265+
)
2266+
)))]
2267+
Err(e) if e.kind() == ErrorKind::Unsupported => return,
2268+
Err(e) => panic!("error setting file times: {e:?}"),
2269+
Ok(_) => {}
2270+
}
2271+
2272+
let metadata = fs::metadata(&path).unwrap();
2273+
assert_eq!(metadata.accessed().unwrap(), accessed);
2274+
assert_eq!(metadata.modified().unwrap(), modified);
2275+
#[cfg(any(windows, target_vendor = "apple"))]
2276+
{
2277+
assert_eq!(metadata.created().unwrap(), created);
2278+
}
2279+
}
2280+
2281+
#[test]
2282+
fn test_fs_set_times_follows_symlink() {
2283+
#[cfg(target_vendor = "apple")]
2284+
use crate::os::darwin::fs::FileTimesExt;
2285+
#[cfg(windows)]
2286+
use crate::os::windows::fs::FileTimesExt;
2287+
2288+
let tmp = tmpdir();
2289+
2290+
// Create a target file
2291+
let target = tmp.join("target");
2292+
File::create(&target).unwrap();
2293+
2294+
// Create a symlink to the target
2295+
#[cfg(unix)]
2296+
let link = tmp.join("link");
2297+
#[cfg(unix)]
2298+
crate::os::unix::fs::symlink(&target, &link).unwrap();
2299+
2300+
#[cfg(windows)]
2301+
let link = tmp.join("link.txt");
2302+
#[cfg(windows)]
2303+
crate::os::windows::fs::symlink_file(&target, &link).unwrap();
2304+
2305+
// Get the symlink's own modified time BEFORE calling set_times (to compare later)
2306+
// We don't check accessed time because reading metadata may update atime on some platforms.
2307+
let link_metadata_before = fs::symlink_metadata(&link).unwrap();
2308+
let link_modified_before = link_metadata_before.modified().unwrap();
2309+
2310+
let mut times = FileTimes::new();
2311+
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
2312+
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
2313+
times = times.set_accessed(accessed).set_modified(modified);
2314+
2315+
#[cfg(any(windows, target_vendor = "apple"))]
2316+
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
2317+
#[cfg(any(windows, target_vendor = "apple"))]
2318+
{
2319+
times = times.set_created(created);
2320+
}
2321+
2322+
// Call fs::set_times on the symlink - it should follow the link and modify the target
2323+
match fs::set_times(&link, times) {
2324+
// Allow unsupported errors on platforms which don't support setting times.
2325+
#[cfg(not(any(
2326+
windows,
2327+
all(
2328+
unix,
2329+
not(any(
2330+
target_os = "android",
2331+
target_os = "redox",
2332+
target_os = "espidf",
2333+
target_os = "horizon"
2334+
))
2335+
)
2336+
)))]
2337+
Err(e) if e.kind() == ErrorKind::Unsupported => return,
2338+
Err(e) => panic!("error setting file times through symlink: {e:?}"),
2339+
Ok(_) => {}
2340+
}
2341+
2342+
// Verify that the TARGET file's times were changed (following the symlink)
2343+
let target_metadata = fs::metadata(&target).unwrap();
2344+
assert_eq!(
2345+
target_metadata.accessed().unwrap(),
2346+
accessed,
2347+
"target file accessed time should match"
2348+
);
2349+
assert_eq!(
2350+
target_metadata.modified().unwrap(),
2351+
modified,
2352+
"target file modified time should match"
2353+
);
2354+
#[cfg(any(windows, target_vendor = "apple"))]
2355+
{
2356+
assert_eq!(
2357+
target_metadata.created().unwrap(),
2358+
created,
2359+
"target file created time should match"
2360+
);
2361+
}
2362+
2363+
// Also verify through the symlink (fs::metadata follows symlinks)
2364+
let link_followed_metadata = fs::metadata(&link).unwrap();
2365+
assert_eq!(link_followed_metadata.accessed().unwrap(), accessed);
2366+
assert_eq!(link_followed_metadata.modified().unwrap(), modified);
2367+
2368+
// Verify that the SYMLINK ITSELF was NOT modified
2369+
// Note: We only check modified time, not accessed time, because reading the symlink
2370+
// metadata may update its atime on some platforms (e.g., Linux).
2371+
let link_metadata_after = fs::symlink_metadata(&link).unwrap();
2372+
assert_eq!(
2373+
link_metadata_after.modified().unwrap(),
2374+
link_modified_before,
2375+
"symlink's own modified time should not change"
2376+
);
2377+
}
2378+
2379+
#[test]
2380+
fn test_fs_set_times_nofollow() {
2381+
#[cfg(target_vendor = "apple")]
2382+
use crate::os::darwin::fs::FileTimesExt;
2383+
#[cfg(windows)]
2384+
use crate::os::windows::fs::FileTimesExt;
2385+
2386+
let tmp = tmpdir();
2387+
2388+
// Create a target file and a symlink to it
2389+
let target = tmp.join("target");
2390+
File::create(&target).unwrap();
2391+
2392+
#[cfg(unix)]
2393+
let link = tmp.join("link");
2394+
#[cfg(unix)]
2395+
crate::os::unix::fs::symlink(&target, &link).unwrap();
2396+
2397+
#[cfg(windows)]
2398+
let link = tmp.join("link.txt");
2399+
#[cfg(windows)]
2400+
crate::os::windows::fs::symlink_file(&target, &link).unwrap();
2401+
2402+
let mut times = FileTimes::new();
2403+
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(11111);
2404+
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(22222);
2405+
times = times.set_accessed(accessed).set_modified(modified);
2406+
2407+
#[cfg(any(windows, target_vendor = "apple"))]
2408+
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(33333);
2409+
#[cfg(any(windows, target_vendor = "apple"))]
2410+
{
2411+
times = times.set_created(created);
2412+
}
2413+
2414+
// Set times on the symlink itself (not following it)
2415+
match fs::set_times_nofollow(&link, times) {
2416+
// Allow unsupported errors on platforms which don't support setting times.
2417+
#[cfg(not(any(
2418+
windows,
2419+
all(
2420+
unix,
2421+
not(any(
2422+
target_os = "android",
2423+
target_os = "redox",
2424+
target_os = "espidf",
2425+
target_os = "horizon"
2426+
))
2427+
)
2428+
)))]
2429+
Err(e) if e.kind() == ErrorKind::Unsupported => return,
2430+
Err(e) => panic!("error setting symlink times: {e:?}"),
2431+
Ok(_) => {}
2432+
}
2433+
2434+
// Read symlink metadata (without following)
2435+
let metadata = fs::symlink_metadata(&link).unwrap();
2436+
assert_eq!(metadata.accessed().unwrap(), accessed);
2437+
assert_eq!(metadata.modified().unwrap(), modified);
2438+
#[cfg(any(windows, target_vendor = "apple"))]
2439+
{
2440+
assert_eq!(metadata.created().unwrap(), created);
2441+
}
2442+
2443+
// Verify that the target file's times were NOT changed
2444+
let target_metadata = fs::metadata(&target).unwrap();
2445+
assert_ne!(target_metadata.accessed().unwrap(), accessed);
2446+
assert_ne!(target_metadata.modified().unwrap(), modified);
2447+
}

0 commit comments

Comments
 (0)