authorbors <bors@rust-lang.org> 2025-09-05 20:49:13 UTC
committerbors <bors@rust-lang.org> 2025-09-05 20:49:13 UTC
log6c699a37235700ab749e3f14147fe41d49c056e8
tree0f9a359fdd990ba03da8f8aa6ba4ca82682dbda5
parent99317ef14d0be42fa4039eea7c5ce50cb4e9aee7
parent55a62d57ed85c8e1cd412c368c72fc2e7dad48f5

Auto merge of #146255 - fmease:rollup-1v0kp8i, r=fmease

Rollup of 11 pull requests Successful merges: - rust-lang/rust#138944 (Add `__isPlatformVersionAtLeast` and `__isOSVersionAtLeast` symbols) - rust-lang/rust#139113 (unstable book: in a sanitizer example, check the code) - rust-lang/rust#145735 (style-guide: Document absence of trailing whitespace) - rust-lang/rust#146041 (tidy: --bless now makes escheck run with --fix) - rust-lang/rust#146144 (compiler: Apply target features to the entry function) - rust-lang/rust#146225 (Simplify `{f16, f32, f64, f128}::midpoint()`) - rust-lang/rust#146234 (change file-is-generated doc comment to inner) - rust-lang/rust#146241 (rustc_infer: change top-level doc comment to inner) - rust-lang/rust#146242 (Ensure that `--html-after-content` option is used to check `scrape_examples_ice` rustdoc GUI test) - rust-lang/rust#146243 (remove couple of redundant clones) - rust-lang/rust#146250 (Bump stage0 rustfmt) Failed merges: - rust-lang/rust#146200 (Simplify rustdoc-gui tester by calling directly browser-ui-test) r? `@ghost` `@rustbot` modify labels: rollup

34 files changed, 1329 insertions(+), 202 deletions(-)

compiler/rustc_codegen_llvm/src/attributes.rs+14-8
......@@ -296,6 +296,19 @@ pub(crate) fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu
296296 .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu))
297297}
298298
299/// Get the `target-features` LLVM attribute.
300pub(crate) fn target_features_attr<'ll>(
301 cx: &CodegenCx<'ll, '_>,
302 function_features: Vec<String>,
303) -> Option<&'ll Attribute> {
304 let global_features = cx.tcx.global_backend_features(()).iter().map(String::as_str);
305 let function_features = function_features.iter().map(String::as_str);
306 let target_features =
307 global_features.chain(function_features).intersperse(",").collect::<String>();
308 (!target_features.is_empty())
309 .then(|| llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features))
310}
311
299312/// Get the `NonLazyBind` LLVM attribute,
300313/// if the codegen options allow skipping the PLT.
301314pub(crate) fn non_lazy_bind_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> {
......@@ -523,14 +536,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
523536 }
524537 }
525538
526 let global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
527 let function_features = function_features.iter().map(|s| s.as_str());
528 let target_features: String =
529 global_features.chain(function_features).intersperse(",").collect();
530
531 if !target_features.is_empty() {
532 to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features));
533 }
539 to_add.extend(target_features_attr(cx, function_features));
534540
535541 attributes::apply_to_llfn(llfn, Function, &to_add);
536542}
compiler/rustc_codegen_llvm/src/context.rs+8-2
......@@ -853,7 +853,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
853853 fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
854854 let entry_name = self.sess().target.entry_name.as_ref();
855855 if self.get_declared_value(entry_name).is_none() {
856 Some(self.declare_entry_fn(
856 let llfn = self.declare_entry_fn(
857857 entry_name,
858858 llvm::CallConv::from_conv(
859859 self.sess().target.entry_abi,
......@@ -861,7 +861,13 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
861861 ),
862862 llvm::UnnamedAddr::Global,
863863 fn_type,
864 ))
864 );
865 attributes::apply_to_llfn(
866 llfn,
867 llvm::AttributePlace::Function,
868 attributes::target_features_attr(self, vec![]).as_slice(),
869 );
870 Some(llfn)
865871 } else {
866872 // If the symbol already exists, it is an error: for example, the user wrote
867873 // #[no_mangle] extern "C" fn main(..) {..}
compiler/rustc_codegen_ssa/src/lib.rs+1-1
......@@ -119,7 +119,7 @@ impl<M> ModuleCodegen<M> {
119119 });
120120
121121 CompiledModule {
122 name: self.name.clone(),
122 name: self.name,
123123 object,
124124 dwarf_object,
125125 bytecode,
compiler/rustc_infer/src/infer/context.rs+1-1
......@@ -1,4 +1,4 @@
1///! Definition of `InferCtxtLike` from the librarified type layer.
1//! Definition of `InferCtxtLike` from the librarified type layer.
22use rustc_hir::def_id::DefId;
33use rustc_middle::traits::ObligationCause;
44use rustc_middle::ty::relate::RelateResult;
compiler/rustc_mir_transform/src/coverage/expansion.rs+1-1
......@@ -82,7 +82,7 @@ impl ExpnNode {
8282 Self {
8383 expn_id,
8484
85 expn_kind: expn_data.kind.clone(),
85 expn_kind: expn_data.kind,
8686 call_site,
8787 call_site_expn_id,
8888
compiler/rustc_resolve/src/late/diagnostics.rs+1-1
......@@ -3099,7 +3099,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
30993099 |err, _, span, message, suggestion, span_suggs| {
31003100 err.multipart_suggestion_verbose(
31013101 message,
3102 std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(),
3102 std::iter::once((span, suggestion)).chain(span_suggs).collect(),
31033103 Applicability::MaybeIncorrect,
31043104 );
31053105 true
compiler/rustc_symbol_mangling/src/v0.rs+6-2
......@@ -82,9 +82,13 @@ pub(super) fn mangle<'tcx>(
8282}
8383
8484pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String {
85 if item_name == "rust_eh_personality" {
85 match item_name {
8686 // rust_eh_personality must not be renamed as LLVM hard-codes the name
87 return "rust_eh_personality".to_owned();
87 "rust_eh_personality" => return item_name.to_owned(),
88 // Apple availability symbols need to not be mangled to be usable by
89 // C/Objective-C code.
90 "__isPlatformVersionAtLeast" | "__isOSVersionAtLeast" => return item_name.to_owned(),
91 _ => {}
8892 }
8993
9094 let prefix = "_R";
compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs+1-1
......@@ -318,7 +318,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
318318 let (expected, found) = if expected_str == found_str {
319319 (join_path_syms(&expected_abs), join_path_syms(&found_abs))
320320 } else {
321 (expected_str.clone(), found_str.clone())
321 (expected_str, found_str)
322322 };
323323
324324 // We've displayed "expected `a::b`, found `a::b`". We add context to
library/core/src/num/f128.rs-8
......@@ -832,7 +832,6 @@ impl f128 {
832832 #[unstable(feature = "f128", issue = "116909")]
833833 #[rustc_const_unstable(feature = "f128", issue = "116909")]
834834 pub const fn midpoint(self, other: f128) -> f128 {
835 const LO: f128 = f128::MIN_POSITIVE * 2.;
836835 const HI: f128 = f128::MAX / 2.;
837836
838837 let (a, b) = (self, other);
......@@ -842,14 +841,7 @@ impl f128 {
842841 if abs_a <= HI && abs_b <= HI {
843842 // Overflow is impossible
844843 (a + b) / 2.
845 } else if abs_a < LO {
846 // Not safe to halve `a` (would underflow)
847 a + (b / 2.)
848 } else if abs_b < LO {
849 // Not safe to halve `b` (would underflow)
850 (a / 2.) + b
851844 } else {
852 // Safe to halve `a` and `b`
853845 (a / 2.) + (b / 2.)
854846 }
855847 }
library/core/src/num/f16.rs-8
......@@ -820,7 +820,6 @@ impl f16 {
820820 #[unstable(feature = "f16", issue = "116909")]
821821 #[rustc_const_unstable(feature = "f16", issue = "116909")]
822822 pub const fn midpoint(self, other: f16) -> f16 {
823 const LO: f16 = f16::MIN_POSITIVE * 2.;
824823 const HI: f16 = f16::MAX / 2.;
825824
826825 let (a, b) = (self, other);
......@@ -830,14 +829,7 @@ impl f16 {
830829 if abs_a <= HI && abs_b <= HI {
831830 // Overflow is impossible
832831 (a + b) / 2.
833 } else if abs_a < LO {
834 // Not safe to halve `a` (would underflow)
835 a + (b / 2.)
836 } else if abs_b < LO {
837 // Not safe to halve `b` (would underflow)
838 (a / 2.) + b
839832 } else {
840 // Safe to halve `a` and `b`
841833 (a / 2.) + (b / 2.)
842834 }
843835 }
library/core/src/num/f32.rs-8
......@@ -1025,7 +1025,6 @@ impl f32 {
10251025 ((self as f64 + other as f64) / 2.0) as f32
10261026 }
10271027 _ => {
1028 const LO: f32 = f32::MIN_POSITIVE * 2.;
10291028 const HI: f32 = f32::MAX / 2.;
10301029
10311030 let (a, b) = (self, other);
......@@ -1035,14 +1034,7 @@ impl f32 {
10351034 if abs_a <= HI && abs_b <= HI {
10361035 // Overflow is impossible
10371036 (a + b) / 2.
1038 } else if abs_a < LO {
1039 // Not safe to halve `a` (would underflow)
1040 a + (b / 2.)
1041 } else if abs_b < LO {
1042 // Not safe to halve `b` (would underflow)
1043 (a / 2.) + b
10441037 } else {
1045 // Safe to halve `a` and `b`
10461038 (a / 2.) + (b / 2.)
10471039 }
10481040 }
library/core/src/num/f64.rs-8
......@@ -1026,7 +1026,6 @@ impl f64 {
10261026 #[stable(feature = "num_midpoint", since = "1.85.0")]
10271027 #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")]
10281028 pub const fn midpoint(self, other: f64) -> f64 {
1029 const LO: f64 = f64::MIN_POSITIVE * 2.;
10301029 const HI: f64 = f64::MAX / 2.;
10311030
10321031 let (a, b) = (self, other);
......@@ -1036,14 +1035,7 @@ impl f64 {
10361035 if abs_a <= HI && abs_b <= HI {
10371036 // Overflow is impossible
10381037 (a + b) / 2.
1039 } else if abs_a < LO {
1040 // Not safe to halve `a` (would underflow)
1041 a + (b / 2.)
1042 } else if abs_b < LO {
1043 // Not safe to halve `b` (would underflow)
1044 (a / 2.) + b
10451038 } else {
1046 // Safe to halve `a` and `b`
10471039 (a / 2.) + (b / 2.)
10481040 }
10491041 }
library/core/src/unicode/unicode_data.rs+1-1
......@@ -1,4 +1,4 @@
1///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!
1//! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!
22// Alphabetic : 1727 bytes, 142759 codepoints in 757 ranges (U+000041 - U+0323B0) using skiplist
33// Case_Ignorable : 1053 bytes, 2749 codepoints in 452 ranges (U+000027 - U+0E01F0) using skiplist
44// Cased : 407 bytes, 4578 codepoints in 159 ranges (U+000041 - U+01F18A) using skiplist
library/std/src/lib.rs+2
......@@ -354,6 +354,7 @@
354354#![feature(hasher_prefixfree_extras)]
355355#![feature(hashmap_internals)]
356356#![feature(hint_must_use)]
357#![feature(int_from_ascii)]
357358#![feature(ip)]
358359#![feature(lazy_get)]
359360#![feature(maybe_uninit_slice)]
......@@ -369,6 +370,7 @@
369370#![feature(slice_internals)]
370371#![feature(slice_ptr_get)]
371372#![feature(slice_range)]
373#![feature(slice_split_once)]
372374#![feature(std_internals)]
373375#![feature(str_internals)]
374376#![feature(sync_unsafe_cell)]
library/std/src/sys/mod.rs+1
......@@ -26,6 +26,7 @@ pub mod io;
2626pub mod net;
2727pub mod os_str;
2828pub mod path;
29pub mod platform_version;
2930pub mod process;
3031pub mod random;
3132pub mod stdio;
library/std/src/sys/platform_version/darwin/core_foundation.rs created+180
......@@ -0,0 +1,180 @@
1//! Minimal utilities for interfacing with a dynamically loaded CoreFoundation.
2#![allow(non_snake_case, non_upper_case_globals)]
3use super::root_relative;
4use crate::ffi::{CStr, c_char, c_void};
5use crate::ptr::null_mut;
6use crate::sys::common::small_c_string::run_path_with_cstr;
7
8// MacTypes.h
9pub(super) type Boolean = u8;
10// CoreFoundation/CFBase.h
11pub(super) type CFTypeID = usize;
12pub(super) type CFOptionFlags = usize;
13pub(super) type CFIndex = isize;
14pub(super) type CFTypeRef = *mut c_void;
15pub(super) type CFAllocatorRef = CFTypeRef;
16pub(super) const kCFAllocatorDefault: CFAllocatorRef = null_mut();
17// CoreFoundation/CFError.h
18pub(super) type CFErrorRef = CFTypeRef;
19// CoreFoundation/CFData.h
20pub(super) type CFDataRef = CFTypeRef;
21// CoreFoundation/CFPropertyList.h
22pub(super) const kCFPropertyListImmutable: CFOptionFlags = 0;
23pub(super) type CFPropertyListFormat = CFIndex;
24pub(super) type CFPropertyListRef = CFTypeRef;
25// CoreFoundation/CFString.h
26pub(super) type CFStringRef = CFTypeRef;
27pub(super) type CFStringEncoding = u32;
28pub(super) const kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
29// CoreFoundation/CFDictionary.h
30pub(super) type CFDictionaryRef = CFTypeRef;
31
32/// An open handle to the dynamically loaded CoreFoundation framework.
33///
34/// This is `dlopen`ed, and later `dlclose`d. This is done to try to avoid
35/// "leaking" the CoreFoundation symbols to the rest of the user's binary if
36/// they decided to not link CoreFoundation themselves.
37///
38/// It is also faster to look up symbols directly via this handle than with
39/// `RTLD_DEFAULT`.
40pub(super) struct CFHandle(*mut c_void);
41
42macro_rules! dlsym_fn {
43 (
44 unsafe fn $name:ident($($param:ident: $param_ty:ty),* $(,)?) $(-> $ret:ty)?;
45 ) => {
46 pub(super) unsafe fn $name(&self, $($param: $param_ty),*) $(-> $ret)? {
47 let ptr = unsafe {
48 libc::dlsym(
49 self.0,
50 concat!(stringify!($name), '\0').as_bytes().as_ptr().cast(),
51 )
52 };
53 if ptr.is_null() {
54 let err = unsafe { CStr::from_ptr(libc::dlerror()) };
55 panic!("could not find function {}: {err:?}", stringify!($name));
56 }
57
58 // SAFETY: Just checked that the symbol isn't NULL, and macro invoker verifies that
59 // the signature is correct.
60 let fnptr = unsafe {
61 crate::mem::transmute::<
62 *mut c_void,
63 unsafe extern "C" fn($($param_ty),*) $(-> $ret)?,
64 >(ptr)
65 };
66
67 // SAFETY: Upheld by caller.
68 unsafe { fnptr($($param),*) }
69 }
70 };
71}
72
73impl CFHandle {
74 /// Link to the CoreFoundation dylib, and look up symbols from that.
75 pub(super) fn new() -> Self {
76 // We explicitly use non-versioned path here, to allow this to work on older iOS devices.
77 let cf_path =
78 root_relative("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation");
79
80 let handle = run_path_with_cstr(&cf_path, &|path| unsafe {
81 Ok(libc::dlopen(path.as_ptr(), libc::RTLD_LAZY | libc::RTLD_LOCAL))
82 })
83 .expect("failed allocating string");
84
85 if handle.is_null() {
86 let err = unsafe { CStr::from_ptr(libc::dlerror()) };
87 panic!("could not open CoreFoundation.framework: {err:?}");
88 }
89
90 Self(handle)
91 }
92
93 pub(super) fn kCFAllocatorNull(&self) -> CFAllocatorRef {
94 // Available: in all CF versions.
95 let static_ptr = unsafe { libc::dlsym(self.0, c"kCFAllocatorNull".as_ptr()) };
96 if static_ptr.is_null() {
97 let err = unsafe { CStr::from_ptr(libc::dlerror()) };
98 panic!("could not find kCFAllocatorNull: {err:?}");
99 }
100 unsafe { *static_ptr.cast() }
101 }
102
103 // CoreFoundation/CFBase.h
104 dlsym_fn!(
105 // Available: in all CF versions.
106 unsafe fn CFRelease(cf: CFTypeRef);
107 );
108 dlsym_fn!(
109 // Available: in all CF versions.
110 unsafe fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
111 );
112
113 // CoreFoundation/CFData.h
114 dlsym_fn!(
115 // Available: in all CF versions.
116 unsafe fn CFDataCreateWithBytesNoCopy(
117 allocator: CFAllocatorRef,
118 bytes: *const u8,
119 length: CFIndex,
120 bytes_deallocator: CFAllocatorRef,
121 ) -> CFDataRef;
122 );
123
124 // CoreFoundation/CFPropertyList.h
125 dlsym_fn!(
126 // Available: since macOS 10.6.
127 unsafe fn CFPropertyListCreateWithData(
128 allocator: CFAllocatorRef,
129 data: CFDataRef,
130 options: CFOptionFlags,
131 format: *mut CFPropertyListFormat,
132 error: *mut CFErrorRef,
133 ) -> CFPropertyListRef;
134 );
135
136 // CoreFoundation/CFString.h
137 dlsym_fn!(
138 // Available: in all CF versions.
139 unsafe fn CFStringGetTypeID() -> CFTypeID;
140 );
141 dlsym_fn!(
142 // Available: in all CF versions.
143 unsafe fn CFStringCreateWithCStringNoCopy(
144 alloc: CFAllocatorRef,
145 c_str: *const c_char,
146 encoding: CFStringEncoding,
147 contents_deallocator: CFAllocatorRef,
148 ) -> CFStringRef;
149 );
150 dlsym_fn!(
151 // Available: in all CF versions.
152 unsafe fn CFStringGetCString(
153 the_string: CFStringRef,
154 buffer: *mut c_char,
155 buffer_size: CFIndex,
156 encoding: CFStringEncoding,
157 ) -> Boolean;
158 );
159
160 // CoreFoundation/CFDictionary.h
161 dlsym_fn!(
162 // Available: in all CF versions.
163 unsafe fn CFDictionaryGetTypeID() -> CFTypeID;
164 );
165 dlsym_fn!(
166 // Available: in all CF versions.
167 unsafe fn CFDictionaryGetValue(
168 the_dict: CFDictionaryRef,
169 key: *const c_void,
170 ) -> *const c_void;
171 );
172}
173
174impl Drop for CFHandle {
175 fn drop(&mut self) {
176 // Ignore errors when closing. This is also what `libloading` does:
177 // https://docs.rs/libloading/0.8.6/src/libloading/os/unix/mod.rs.html#374
178 let _ = unsafe { libc::dlclose(self.0) };
179 }
180}
library/std/src/sys/platform_version/darwin/mod.rs created+351
......@@ -0,0 +1,351 @@
1use self::core_foundation::{
2 CFDictionaryRef, CFHandle, CFIndex, CFStringRef, CFTypeRef, kCFAllocatorDefault,
3 kCFPropertyListImmutable, kCFStringEncodingUTF8,
4};
5use crate::borrow::Cow;
6use crate::bstr::ByteStr;
7use crate::ffi::{CStr, c_char};
8use crate::num::{NonZero, ParseIntError};
9use crate::path::{Path, PathBuf};
10use crate::ptr::null_mut;
11use crate::sync::atomic::{AtomicU32, Ordering};
12use crate::{env, fs};
13
14mod core_foundation;
15mod public_extern;
16#[cfg(test)]
17mod tests;
18
19/// The version of the operating system.
20///
21/// We use a packed u32 here to allow for fast comparisons and to match Mach-O's `LC_BUILD_VERSION`.
22type OSVersion = u32;
23
24/// Combine parts of a version into an [`OSVersion`].
25///
26/// The size of the parts are inherently limited by Mach-O's `LC_BUILD_VERSION`.
27#[inline]
28const fn pack_os_version(major: u16, minor: u8, patch: u8) -> OSVersion {
29 let (major, minor, patch) = (major as u32, minor as u32, patch as u32);
30 (major << 16) | (minor << 8) | patch
31}
32
33/// [`pack_os_version`], but takes `i32` and saturates.
34///
35/// Instead of using e.g. `major as u16`, which truncates.
36#[inline]
37fn pack_i32_os_version(major: i32, minor: i32, patch: i32) -> OSVersion {
38 let major: u16 = major.try_into().unwrap_or(u16::MAX);
39 let minor: u8 = minor.try_into().unwrap_or(u8::MAX);
40 let patch: u8 = patch.try_into().unwrap_or(u8::MAX);
41 pack_os_version(major, minor, patch)
42}
43
44/// Get the current OS version, packed according to [`pack_os_version`].
45///
46/// # Semantics
47///
48/// The reported version on macOS might be 10.16 if the SDK version of the binary is less than 11.0.
49/// This is a workaround that Apple implemented to handle applications that assumed that macOS
50/// versions would always start with "10", see:
51/// <https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.81.4/libsyscall/wrappers/system-version-compat.c>
52///
53/// It _is_ possible to get the real version regardless of the SDK version of the binary, this is
54/// what Zig does:
55/// <https://github.com/ziglang/zig/blob/0.13.0/lib/std/zig/system/darwin/macos.zig>
56///
57/// We choose to not do that, and instead follow Apple's behaviour here, and return 10.16 when
58/// compiled with an older SDK; the user should instead upgrade their tooling.
59///
60/// NOTE: `rustc` currently doesn't set the right SDK version when linking with ld64, so this will
61/// have the wrong behaviour with `-Clinker=ld` on x86_64. But that's a `rustc` bug:
62/// <https://github.com/rust-lang/rust/issues/129432>
63#[inline]
64fn current_version() -> OSVersion {
65 // Cache the lookup for performance.
66 //
67 // 0.0.0 is never going to be a valid version ("vtool" reports "n/a" on 0 versions), so we use
68 // that as our sentinel value.
69 static CURRENT_VERSION: AtomicU32 = AtomicU32::new(0);
70
71 // We use relaxed atomics instead of e.g. a `Once`, it doesn't matter if multiple threads end up
72 // racing to read or write the version, `lookup_version` should be idempotent and always return
73 // the same value.
74 //
75 // `compiler-rt` uses `dispatch_once`, but that's overkill for the reasons above.
76 let version = CURRENT_VERSION.load(Ordering::Relaxed);
77 if version == 0 {
78 let version = lookup_version().get();
79 CURRENT_VERSION.store(version, Ordering::Relaxed);
80 version
81 } else {
82 version
83 }
84}
85
86/// Look up the os version.
87///
88/// # Aborts
89///
90/// Aborts if reading or parsing the version fails (or if the system was out of memory).
91///
92/// We deliberately choose to abort, as having this silently return an invalid OS version would be
93/// impossible for a user to debug.
94// The lookup is costly and should be on the cold path because of the cache in `current_version`.
95#[cold]
96// Micro-optimization: We use `extern "C"` to abort on panic, allowing `current_version` (inlined)
97// to be free of unwind handling. Aborting is required for `__isPlatformVersionAtLeast` anyhow.
98extern "C" fn lookup_version() -> NonZero<OSVersion> {
99 // Try to read from `sysctl` first (faster), but if that fails, fall back to reading the
100 // property list (this is roughly what `_availability_version_check` does internally).
101 let version = version_from_sysctl().unwrap_or_else(version_from_plist);
102
103 // Use `NonZero` to try to make it clearer to the optimizer that this will never return 0.
104 NonZero::new(version).expect("version cannot be 0.0.0")
105}
106
107/// Read the version from `kern.osproductversion` or `kern.iossupportversion`.
108///
109/// This is faster than `version_from_plist`, since it doesn't need to invoke `dlsym`.
110fn version_from_sysctl() -> Option<OSVersion> {
111 // This won't work in the simulator, as `kern.osproductversion` returns the host macOS version,
112 // and `kern.iossupportversion` returns the host macOS' iOSSupportVersion (while you can run
113 // simulators with many different iOS versions).
114 if cfg!(target_abi = "sim") {
115 // Fall back to `version_from_plist` on these targets.
116 return None;
117 }
118
119 let sysctl_version = |name: &CStr| {
120 let mut buf: [u8; 32] = [0; 32];
121 let mut size = buf.len();
122 let ptr = buf.as_mut_ptr().cast();
123 let ret = unsafe { libc::sysctlbyname(name.as_ptr(), ptr, &mut size, null_mut(), 0) };
124 if ret != 0 {
125 // This sysctl is not available.
126 return None;
127 }
128 let buf = &buf[..(size - 1)];
129
130 if buf.is_empty() {
131 // The buffer may be empty when using `kern.iossupportversion` on an actual iOS device,
132 // or on visionOS when running under "Designed for iPad".
133 //
134 // In that case, fall back to `kern.osproductversion`.
135 return None;
136 }
137
138 Some(parse_os_version(buf).unwrap_or_else(|err| {
139 panic!("failed parsing version from sysctl ({}): {err}", ByteStr::new(buf))
140 }))
141 };
142
143 // When `target_os = "ios"`, we may be in many different states:
144 // - Native iOS device.
145 // - iOS Simulator.
146 // - Mac Catalyst.
147 // - Mac + "Designed for iPad".
148 // - Native visionOS device + "Designed for iPad".
149 // - visionOS simulator + "Designed for iPad".
150 //
151 // Of these, only native, Mac Catalyst and simulators can be differentiated at compile-time
152 // (with `target_abi = ""`, `target_abi = "macabi"` and `target_abi = "sim"` respectively).
153 //
154 // That is, "Designed for iPad" will act as iOS at compile-time, but the `ProductVersion` will
155 // still be the host macOS or visionOS version.
156 //
157 // Furthermore, we can't even reliably differentiate between these at runtime, since
158 // `dyld_get_active_platform` isn't publicly available.
159 //
160 // Fortunately, we won't need to know any of that; we can simply attempt to get the
161 // `iOSSupportVersion` (which may be set on native iOS too, but then it will be set to the host
162 // iOS version), and if that fails, fall back to the `ProductVersion`.
163 if cfg!(target_os = "ios") {
164 // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.81.4/bsd/kern/kern_sysctl.c#L2077-L2100
165 if let Some(ios_support_version) = sysctl_version(c"kern.iossupportversion") {
166 return Some(ios_support_version);
167 }
168
169 // On Mac Catalyst, if we failed looking up `iOSSupportVersion`, we don't want to
170 // accidentally fall back to `ProductVersion`.
171 if cfg!(target_abi = "macabi") {
172 return None;
173 }
174 }
175
176 // Introduced in macOS 10.13.4.
177 // https://github.com/apple-oss-distributions/xnu/blob/xnu-11215.81.4/bsd/kern/kern_sysctl.c#L2015-L2051
178 sysctl_version(c"kern.osproductversion")
179}
180
181/// Look up the current OS version(s) from `/System/Library/CoreServices/SystemVersion.plist`.
182///
183/// More specifically, from the `ProductVersion` and `iOSSupportVersion` keys, and from
184/// `$IPHONE_SIMULATOR_ROOT/System/Library/CoreServices/SystemVersion.plist` on the simulator.
185///
186/// This file was introduced in macOS 10.3, which is well below the minimum supported version by
187/// `rustc`, which is (at the time of writing) macOS 10.12.
188///
189/// # Implementation
190///
191/// We do roughly the same thing in here as `compiler-rt`, and dynamically look up CoreFoundation
192/// utilities for parsing PLists (to avoid having to re-implement that in here, as pulling in a full
193/// PList parser into `std` seems costly).
194///
195/// If this is found to be undesirable, we _could_ possibly hack it by parsing the PList manually
196/// (it seems to use the plain-text "xml1" encoding/format in all versions), but that seems brittle.
197fn version_from_plist() -> OSVersion {
198 // Read `SystemVersion.plist`. Always present on Apple platforms, reading it cannot fail.
199 let path = root_relative("/System/Library/CoreServices/SystemVersion.plist");
200 let plist_buffer = fs::read(&path).unwrap_or_else(|e| panic!("failed reading {path:?}: {e}"));
201 let cf_handle = CFHandle::new();
202 parse_version_from_plist(&cf_handle, &plist_buffer)
203}
204
205/// Parse OS version from the given PList.
206///
207/// Split out from [`version_from_plist`] to allow for testing.
208fn parse_version_from_plist(cf_handle: &CFHandle, plist_buffer: &[u8]) -> OSVersion {
209 let plist_data = unsafe {
210 cf_handle.CFDataCreateWithBytesNoCopy(
211 kCFAllocatorDefault,
212 plist_buffer.as_ptr(),
213 plist_buffer.len() as CFIndex,
214 cf_handle.kCFAllocatorNull(),
215 )
216 };
217 assert!(!plist_data.is_null(), "failed creating CFData");
218 let _plist_data_release = Deferred(|| unsafe { cf_handle.CFRelease(plist_data) });
219
220 let plist = unsafe {
221 cf_handle.CFPropertyListCreateWithData(
222 kCFAllocatorDefault,
223 plist_data,
224 kCFPropertyListImmutable,
225 null_mut(), // Don't care about the format of the PList.
226 null_mut(), // Don't care about the error data.
227 )
228 };
229 assert!(!plist.is_null(), "failed reading PList in SystemVersion.plist");
230 let _plist_release = Deferred(|| unsafe { cf_handle.CFRelease(plist) });
231
232 assert_eq!(
233 unsafe { cf_handle.CFGetTypeID(plist) },
234 unsafe { cf_handle.CFDictionaryGetTypeID() },
235 "SystemVersion.plist did not contain a dictionary at the top level"
236 );
237 let plist: CFDictionaryRef = plist.cast();
238
239 // Same logic as in `version_from_sysctl`.
240 if cfg!(target_os = "ios") {
241 if let Some(ios_support_version) =
242 unsafe { string_version_key(cf_handle, plist, c"iOSSupportVersion") }
243 {
244 return ios_support_version;
245 }
246
247 // Force Mac Catalyst to use iOSSupportVersion (do not fall back to ProductVersion).
248 if cfg!(target_abi = "macabi") {
249 panic!("expected iOSSupportVersion in SystemVersion.plist");
250 }
251 }
252
253 // On all other platforms, we can find the OS version by simply looking at `ProductVersion`.
254 unsafe { string_version_key(cf_handle, plist, c"ProductVersion") }
255 .expect("expected ProductVersion in SystemVersion.plist")
256}
257
258/// Look up a string key in a CFDictionary, and convert it to an [`OSVersion`].
259unsafe fn string_version_key(
260 cf_handle: &CFHandle,
261 plist: CFDictionaryRef,
262 lookup_key: &CStr,
263) -> Option<OSVersion> {
264 let cf_lookup_key = unsafe {
265 cf_handle.CFStringCreateWithCStringNoCopy(
266 kCFAllocatorDefault,
267 lookup_key.as_ptr(),
268 kCFStringEncodingUTF8,
269 cf_handle.kCFAllocatorNull(),
270 )
271 };
272 assert!(!cf_lookup_key.is_null(), "failed creating CFString");
273 let _lookup_key_release = Deferred(|| unsafe { cf_handle.CFRelease(cf_lookup_key) });
274
275 let value: CFTypeRef =
276 unsafe { cf_handle.CFDictionaryGetValue(plist, cf_lookup_key) }.cast_mut();
277 // `CFDictionaryGetValue` is a "getter", so we should not release,
278 // the value is held alive internally by the CFDictionary, see:
279 // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmPractical.html#//apple_ref/doc/uid/TP40004447-SW12
280 if value.is_null() {
281 return None;
282 }
283
284 assert_eq!(
285 unsafe { cf_handle.CFGetTypeID(value) },
286 unsafe { cf_handle.CFStringGetTypeID() },
287 "key in SystemVersion.plist must be a string"
288 );
289 let value: CFStringRef = value.cast();
290
291 let mut version_str = [0u8; 32];
292 let ret = unsafe {
293 cf_handle.CFStringGetCString(
294 value,
295 version_str.as_mut_ptr().cast::<c_char>(),
296 version_str.len() as CFIndex,
297 kCFStringEncodingUTF8,
298 )
299 };
300 assert_ne!(ret, 0, "failed getting string from CFString");
301
302 let version_str =
303 CStr::from_bytes_until_nul(&version_str).expect("failed converting CFString to CStr");
304
305 Some(parse_os_version(version_str.to_bytes()).unwrap_or_else(|err| {
306 panic!(
307 "failed parsing version from PList ({}): {err}",
308 ByteStr::new(version_str.to_bytes())
309 )
310 }))
311}
312
313/// Parse an OS version from a bytestring like b"10.1" or b"14.3.7".
314fn parse_os_version(version: &[u8]) -> Result<OSVersion, ParseIntError> {
315 if let Some((major, minor)) = version.split_once(|&b| b == b'.') {
316 let major = u16::from_ascii(major)?;
317 if let Some((minor, patch)) = minor.split_once(|&b| b == b'.') {
318 let minor = u8::from_ascii(minor)?;
319 let patch = u8::from_ascii(patch)?;
320 Ok(pack_os_version(major, minor, patch))
321 } else {
322 let minor = u8::from_ascii(minor)?;
323 Ok(pack_os_version(major, minor, 0))
324 }
325 } else {
326 let major = u16::from_ascii(version)?;
327 Ok(pack_os_version(major, 0, 0))
328 }
329}
330
331/// Get a path relative to the root directory in which all files for the current env are located.
332fn root_relative(path: &str) -> Cow<'_, Path> {
333 if cfg!(target_abi = "sim") {
334 let mut root = PathBuf::from(env::var_os("IPHONE_SIMULATOR_ROOT").expect(
335 "environment variable `IPHONE_SIMULATOR_ROOT` must be set when executing under simulator",
336 ));
337 // Convert absolute path to relative path, to make the `.push` work as expected.
338 root.push(Path::new(path).strip_prefix("/").unwrap());
339 root.into()
340 } else {
341 Path::new(path).into()
342 }
343}
344
345struct Deferred<F: FnMut()>(F);
346
347impl<F: FnMut()> Drop for Deferred<F> {
348 fn drop(&mut self) {
349 (self.0)();
350 }
351}
library/std/src/sys/platform_version/darwin/public_extern.rs created+151
......@@ -0,0 +1,151 @@
1//! # Runtime version checking ABI for other compilers.
2//!
3//! The symbols in this file are useful for us to expose to allow linking code written in the
4//! following languages when using their version checking functionality:
5//! - Clang's `__builtin_available` macro.
6//! - Objective-C's `@available`.
7//! - Swift's `#available`,
8//!
9//! Without Rust exposing these symbols, the user would encounter a linker error when linking to
10//! C/Objective-C/Swift libraries using these features.
11//!
12//! The presence of these symbols is mostly considered a quality-of-implementation detail, and
13//! should not be relied upon to be available. The intended effect is that linking with code built
14//! with Clang's `__builtin_available` (or similar) will continue to work. For example, we may
15//! decide to remove `__isOSVersionAtLeast` if support for Clang 11 (Xcode 11) is dropped.
16//!
17//! ## Background
18//!
19//! The original discussion of this feature can be found at:
20//! - <https://lists.llvm.org/pipermail/cfe-dev/2016-July/049851.html>
21//! - <https://reviews.llvm.org/D27827>
22//! - <https://reviews.llvm.org/D30136>
23//!
24//! And the upstream implementation of these can be found in `compiler-rt`:
25//! <https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/compiler-rt/lib/builtins/os_version_check.c>
26//!
27//! Ideally, these symbols should probably have been a part of Apple's `libSystem.dylib`, both
28//! because their implementation is quite complex, using allocation, environment variables, file
29//! access and dynamic library loading (and emitting all of this into every binary).
30//!
31//! The reason why Apple chose to not do that originally is lost to the sands of time, but a good
32//! reason would be that implementing it as part of `compiler-rt` allowed them to back-deploy this
33//! to older OSes immediately.
34//!
35//! In Rust's case, while we may provide a feature similar to `@available` in the future, we will
36//! probably do so as a macro exposed by `std` (and not as a compiler builtin). So implementing this
37//! in `std` makes sense, since then we can implement it using `std` utilities, and we can avoid
38//! having `compiler-builtins` depend on `libSystem.dylib`.
39//!
40//! This does mean that users that attempt to link C/Objective-C/Swift code _and_ use `#![no_std]`
41//! in all their crates may get a linker error because these symbols are missing. Using `no_std` is
42//! quite uncommon on Apple systems though, so it's probably fine to not support this use-case.
43//!
44//! The workaround would be to link `libclang_rt.osx.a` or otherwise use Clang's `compiler-rt`.
45//!
46//! See also discussion in <https://github.com/rust-lang/compiler-builtins/pull/794>.
47//!
48//! ## Implementation details
49//!
50//! NOTE: Since macOS 10.15, `libSystem.dylib` _has_ actually provided the undocumented
51//! `_availability_version_check` via `libxpc` for doing the version lookup (zippered, which is why
52//! it requires a platform parameter to differentiate between macOS and Mac Catalyst), though its
53//! usage may be a bit dangerous, see:
54//! - <https://reviews.llvm.org/D150397>
55//! - <https://github.com/llvm/llvm-project/issues/64227>
56//!
57//! Besides, we'd need to implement the version lookup via PList to support older versions anyhow,
58//! so we might as well use that everywhere (since it can also be optimized more after inlining).
59
60#![allow(non_snake_case)]
61
62use super::{current_version, pack_i32_os_version};
63
64/// Whether the current platform's OS version is higher than or equal to the given version.
65///
66/// The first argument is the _base_ Mach-O platform (i.e. `PLATFORM_MACOS`, `PLATFORM_IOS`, etc.,
67/// but not `PLATFORM_IOSSIMULATOR` or `PLATFORM_MACCATALYST`) of the invoking binary.
68///
69/// Arguments are specified statically by Clang. Inlining with LTO should allow the versions to be
70/// combined into a single `u32`, which should make comparisons faster, and should make the
71/// `BASE_TARGET_PLATFORM` check a no-op.
72//
73// SAFETY: The signature is the same as what Clang expects, and we export weakly to allow linking
74// both this and `libclang_rt.*.a`, similar to how `compiler-builtins` does it:
75// https://github.com/rust-lang/compiler-builtins/blob/0.1.113/src/macros.rs#L494
76//
77// NOTE: This symbol has a workaround in the compiler's symbol mangling to avoid mangling it, while
78// still not exposing it from non-cdylib (like `#[no_mangle]` would).
79#[rustc_std_internal_symbol]
80// extern "C" is correct, Clang assumes the function cannot unwind:
81// https://github.com/llvm/llvm-project/blob/llvmorg-20.1.0/clang/lib/CodeGen/CGObjC.cpp#L3980
82//
83// If an error happens in this, we instead abort the process.
84pub(super) extern "C" fn __isPlatformVersionAtLeast(
85 platform: i32,
86 major: i32,
87 minor: i32,
88 subminor: i32,
89) -> i32 {
90 let version = pack_i32_os_version(major, minor, subminor);
91
92 // Mac Catalyst is a technology that allows macOS to run in a different "mode" that closely
93 // resembles iOS (and has iOS libraries like UIKit available).
94 //
95 // (Apple has added a "Designed for iPad" mode later on that allows running iOS apps
96 // natively, but we don't need to think too much about those, since they link to
97 // iOS-specific system binaries as well).
98 //
99 // To support Mac Catalyst, Apple added the concept of a "zippered" binary, which is a single
100 // binary that can be run on both macOS and Mac Catalyst (has two `LC_BUILD_VERSION` Mach-O
101 // commands, one set to `PLATFORM_MACOS` and one to `PLATFORM_MACCATALYST`).
102 //
103 // Most system libraries are zippered, which allows re-use across macOS and Mac Catalyst.
104 // This includes the `libclang_rt.osx.a` shipped with Xcode! This means that `compiler-rt`
105 // can't statically know whether it's compiled for macOS or Mac Catalyst, and thus this new
106 // API (which replaces `__isOSVersionAtLeast`) is needed.
107 //
108 // In short:
109 // normal binary calls normal compiler-rt --> `__isOSVersionAtLeast` was enough
110 // normal binary calls zippered compiler-rt --> `__isPlatformVersionAtLeast` required
111 // zippered binary calls zippered compiler-rt --> `__isPlatformOrVariantPlatformVersionAtLeast` called
112
113 // FIXME(madsmtm): `rustc` doesn't support zippered binaries yet, see rust-lang/rust#131216.
114 // But once it does, we need the pre-compiled `std` shipped with rustup to be zippered, and thus
115 // we also need to handle the `platform` difference here:
116 //
117 // if cfg!(target_os = "macos") && platform == 2 /* PLATFORM_IOS */ && cfg!(zippered) {
118 // return (version.to_u32() <= current_ios_version()) as i32;
119 // }
120 //
121 // `__isPlatformOrVariantPlatformVersionAtLeast` would also need to be implemented.
122
123 // The base Mach-O platform for the current target.
124 const BASE_TARGET_PLATFORM: i32 = if cfg!(target_os = "macos") {
125 1 // PLATFORM_MACOS
126 } else if cfg!(target_os = "ios") {
127 2 // PLATFORM_IOS
128 } else if cfg!(target_os = "tvos") {
129 3 // PLATFORM_TVOS
130 } else if cfg!(target_os = "watchos") {
131 4 // PLATFORM_WATCHOS
132 } else if cfg!(target_os = "visionos") {
133 11 // PLATFORM_VISIONOS
134 } else {
135 0 // PLATFORM_UNKNOWN
136 };
137 debug_assert_eq!(
138 platform, BASE_TARGET_PLATFORM,
139 "invalid platform provided to __isPlatformVersionAtLeast",
140 );
141
142 (version <= current_version()) as i32
143}
144
145/// Old entry point for availability. Used when compiling with older Clang versions.
146// SAFETY: Same as for `__isPlatformVersionAtLeast`.
147#[rustc_std_internal_symbol]
148pub(super) extern "C" fn __isOSVersionAtLeast(major: i32, minor: i32, subminor: i32) -> i32 {
149 let version = pack_i32_os_version(major, minor, subminor);
150 (version <= current_version()) as i32
151}
library/std/src/sys/platform_version/darwin/tests.rs created+379
......@@ -0,0 +1,379 @@
1use super::public_extern::*;
2use super::*;
3use crate::process::Command;
4
5#[test]
6fn test_general_available() {
7 // Lowest version always available.
8 assert_eq!(__isOSVersionAtLeast(0, 0, 0), 1);
9 // This high version never available.
10 assert_eq!(__isOSVersionAtLeast(9999, 99, 99), 0);
11}
12
13#[test]
14fn test_saturating() {
15 // Higher version than supported by OSVersion -> make sure we saturate.
16 assert_eq!(__isOSVersionAtLeast(0x10000, 0, 0), 0);
17}
18
19#[test]
20#[cfg_attr(not(target_os = "macos"), ignore = "`sw_vers` is only available on host macOS")]
21fn compare_against_sw_vers() {
22 let sw_vers = Command::new("sw_vers").arg("-productVersion").output().unwrap().stdout;
23 let sw_vers = String::from_utf8(sw_vers).unwrap();
24 let mut sw_vers = sw_vers.trim().split('.');
25
26 let major: i32 = sw_vers.next().unwrap().parse().unwrap();
27 let minor: i32 = sw_vers.next().unwrap_or("0").parse().unwrap();
28 let subminor: i32 = sw_vers.next().unwrap_or("0").parse().unwrap();
29 assert_eq!(sw_vers.count(), 0);
30
31 // Current version is available
32 assert_eq!(__isOSVersionAtLeast(major, minor, subminor), 1);
33
34 // One lower is available
35 assert_eq!(__isOSVersionAtLeast(major, minor, subminor.saturating_sub(1)), 1);
36 assert_eq!(__isOSVersionAtLeast(major, minor.saturating_sub(1), subminor), 1);
37 assert_eq!(__isOSVersionAtLeast(major.saturating_sub(1), minor, subminor), 1);
38
39 // One higher isn't available
40 assert_eq!(__isOSVersionAtLeast(major, minor, subminor + 1), 0);
41 assert_eq!(__isOSVersionAtLeast(major, minor + 1, subminor), 0);
42 assert_eq!(__isOSVersionAtLeast(major + 1, minor, subminor), 0);
43
44 // Test directly against the lookup
45 assert_eq!(lookup_version().get(), pack_os_version(major as _, minor as _, subminor as _));
46}
47
48#[test]
49fn sysctl_same_as_in_plist() {
50 if let Some(version) = version_from_sysctl() {
51 assert_eq!(version, version_from_plist());
52 }
53}
54
55#[test]
56fn lookup_idempotent() {
57 let version = lookup_version();
58 for _ in 0..10 {
59 assert_eq!(version, lookup_version());
60 }
61}
62
63/// Test parsing a bunch of different PLists found in the wild, to ensure that
64/// if we decide to parse it without CoreFoundation in the future, that it
65/// would continue to work, even on older platforms.
66#[test]
67fn parse_plist() {
68 #[track_caller]
69 fn check(
70 (major, minor, patch): (u16, u8, u8),
71 ios_version: Option<(u16, u8, u8)>,
72 plist: &str,
73 ) {
74 let expected = if cfg!(target_os = "ios") {
75 if let Some((ios_major, ios_minor, ios_patch)) = ios_version {
76 pack_os_version(ios_major, ios_minor, ios_patch)
77 } else if cfg!(target_abi = "macabi") {
78 // Skip checking iOS version on Mac Catalyst.
79 return;
80 } else {
81 // iOS version will be parsed from ProductVersion
82 pack_os_version(major, minor, patch)
83 }
84 } else {
85 pack_os_version(major, minor, patch)
86 };
87 let cf_handle = CFHandle::new();
88 assert_eq!(expected, parse_version_from_plist(&cf_handle, plist.as_bytes()));
89 }
90
91 // macOS 10.3.0
92 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
93 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
94 <plist version="1.0">
95 <dict>
96 <key>ProductBuildVersion</key>
97 <string>7B85</string>
98 <key>ProductCopyright</key>
99 <string>Apple Computer, Inc. 1983-2003</string>
100 <key>ProductName</key>
101 <string>Mac OS X</string>
102 <key>ProductUserVisibleVersion</key>
103 <string>10.3</string>
104 <key>ProductVersion</key>
105 <string>10.3</string>
106 </dict>
107 </plist>
108 "#;
109 check((10, 3, 0), None, plist);
110
111 // macOS 10.7.5
112 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
113 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
114 <plist version="1.0">
115 <dict>
116 <key>ProductBuildVersion</key>
117 <string>11G63</string>
118 <key>ProductCopyright</key>
119 <string>1983-2012 Apple Inc.</string>
120 <key>ProductName</key>
121 <string>Mac OS X</string>
122 <key>ProductUserVisibleVersion</key>
123 <string>10.7.5</string>
124 <key>ProductVersion</key>
125 <string>10.7.5</string>
126 </dict>
127 </plist>
128 "#;
129 check((10, 7, 5), None, plist);
130
131 // macOS 14.7.4
132 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
133 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
134 <plist version="1.0">
135 <dict>
136 <key>BuildID</key>
137 <string>6A558D8A-E2EA-11EF-A1D3-6222CAA672A8</string>
138 <key>ProductBuildVersion</key>
139 <string>23H420</string>
140 <key>ProductCopyright</key>
141 <string>1983-2025 Apple Inc.</string>
142 <key>ProductName</key>
143 <string>macOS</string>
144 <key>ProductUserVisibleVersion</key>
145 <string>14.7.4</string>
146 <key>ProductVersion</key>
147 <string>14.7.4</string>
148 <key>iOSSupportVersion</key>
149 <string>17.7</string>
150 </dict>
151 </plist>
152 "#;
153 check((14, 7, 4), Some((17, 7, 0)), plist);
154
155 // SystemVersionCompat.plist on macOS 14.7.4
156 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
157 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
158 <plist version="1.0">
159 <dict>
160 <key>BuildID</key>
161 <string>6A558D8A-E2EA-11EF-A1D3-6222CAA672A8</string>
162 <key>ProductBuildVersion</key>
163 <string>23H420</string>
164 <key>ProductCopyright</key>
165 <string>1983-2025 Apple Inc.</string>
166 <key>ProductName</key>
167 <string>Mac OS X</string>
168 <key>ProductUserVisibleVersion</key>
169 <string>10.16</string>
170 <key>ProductVersion</key>
171 <string>10.16</string>
172 <key>iOSSupportVersion</key>
173 <string>17.7</string>
174 </dict>
175 </plist>
176 "#;
177 check((10, 16, 0), Some((17, 7, 0)), plist);
178
179 // macOS 15.4 Beta 24E5238a
180 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
181 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
182 <plist version="1.0">
183 <dict>
184 <key>BuildID</key>
185 <string>67A50F62-00DA-11F0-BDB6-F99BB8310D2A</string>
186 <key>ProductBuildVersion</key>
187 <string>24E5238a</string>
188 <key>ProductCopyright</key>
189 <string>1983-2025 Apple Inc.</string>
190 <key>ProductName</key>
191 <string>macOS</string>
192 <key>ProductUserVisibleVersion</key>
193 <string>15.4</string>
194 <key>ProductVersion</key>
195 <string>15.4</string>
196 <key>iOSSupportVersion</key>
197 <string>18.4</string>
198 </dict>
199 </plist>
200 "#;
201 check((15, 4, 0), Some((18, 4, 0)), plist);
202
203 // iOS Simulator 17.5
204 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
205 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
206 <plist version="1.0">
207 <dict>
208 <key>BuildID</key>
209 <string>210B8A2C-09C3-11EF-9DB8-273A64AEFA1C</string>
210 <key>ProductBuildVersion</key>
211 <string>21F79</string>
212 <key>ProductCopyright</key>
213 <string>1983-2024 Apple Inc.</string>
214 <key>ProductName</key>
215 <string>iPhone OS</string>
216 <key>ProductVersion</key>
217 <string>17.5</string>
218 </dict>
219 </plist>
220 "#;
221 check((17, 5, 0), None, plist);
222
223 // visionOS Simulator 2.3
224 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
225 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
226 <plist version="1.0">
227 <dict>
228 <key>BuildID</key>
229 <string>57CEFDE6-D079-11EF-837C-8B8C7961D0AC</string>
230 <key>ProductBuildVersion</key>
231 <string>22N895</string>
232 <key>ProductCopyright</key>
233 <string>1983-2025 Apple Inc.</string>
234 <key>ProductName</key>
235 <string>xrOS</string>
236 <key>ProductVersion</key>
237 <string>2.3</string>
238 <key>SystemImageID</key>
239 <string>D332C7F1-08DF-4DD9-8122-94EF39A1FB92</string>
240 <key>iOSSupportVersion</key>
241 <string>18.3</string>
242 </dict>
243 </plist>
244 "#;
245 check((2, 3, 0), Some((18, 3, 0)), plist);
246
247 // tvOS Simulator 18.2
248 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
249 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
250 <plist version="1.0">
251 <dict>
252 <key>BuildID</key>
253 <string>617587B0-B059-11EF-BE70-4380EDE44645</string>
254 <key>ProductBuildVersion</key>
255 <string>22K154</string>
256 <key>ProductCopyright</key>
257 <string>1983-2024 Apple Inc.</string>
258 <key>ProductName</key>
259 <string>Apple TVOS</string>
260 <key>ProductVersion</key>
261 <string>18.2</string>
262 <key>SystemImageID</key>
263 <string>8BB5A425-33F0-4821-9F93-40E7ED92F4E0</string>
264 </dict>
265 </plist>
266 "#;
267 check((18, 2, 0), None, plist);
268
269 // watchOS Simulator 11.2
270 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
271 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
272 <plist version="1.0">
273 <dict>
274 <key>BuildID</key>
275 <string>BAAE2D54-B122-11EF-BF78-C6C6836B724A</string>
276 <key>ProductBuildVersion</key>
277 <string>22S99</string>
278 <key>ProductCopyright</key>
279 <string>1983-2024 Apple Inc.</string>
280 <key>ProductName</key>
281 <string>Watch OS</string>
282 <key>ProductVersion</key>
283 <string>11.2</string>
284 <key>SystemImageID</key>
285 <string>79F773E2-2041-43B4-98EE-FAE52402AE95</string>
286 </dict>
287 </plist>
288 "#;
289 check((11, 2, 0), None, plist);
290
291 // iOS 9.3.6
292 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
293 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
294 <plist version="1.0">
295 <dict>
296 <key>ProductBuildVersion</key>
297 <string>13G37</string>
298 <key>ProductCopyright</key>
299 <string>1983-2019 Apple Inc.</string>
300 <key>ProductName</key>
301 <string>iPhone OS</string>
302 <key>ProductVersion</key>
303 <string>9.3.6</string>
304 </dict>
305 </plist>
306 "#;
307 check((9, 3, 6), None, plist);
308}
309
310#[test]
311#[should_panic = "SystemVersion.plist did not contain a dictionary at the top level"]
312fn invalid_plist() {
313 let cf_handle = CFHandle::new();
314 let _ = parse_version_from_plist(&cf_handle, b"INVALID");
315}
316
317#[test]
318#[cfg_attr(
319 target_abi = "macabi",
320 should_panic = "expected iOSSupportVersion in SystemVersion.plist"
321)]
322#[cfg_attr(
323 not(target_abi = "macabi"),
324 should_panic = "expected ProductVersion in SystemVersion.plist"
325)]
326fn empty_plist() {
327 let plist = r#"<?xml version="1.0" encoding="UTF-8"?>
328 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
329 <plist version="1.0">
330 <dict>
331 </dict>
332 </plist>
333 "#;
334 let cf_handle = CFHandle::new();
335 let _ = parse_version_from_plist(&cf_handle, plist.as_bytes());
336}
337
338#[test]
339fn parse_version() {
340 #[track_caller]
341 fn check(major: u16, minor: u8, patch: u8, version: &str) {
342 assert_eq!(
343 pack_os_version(major, minor, patch),
344 parse_os_version(version.as_bytes()).unwrap()
345 )
346 }
347
348 check(0, 0, 0, "0");
349 check(0, 0, 0, "0.0.0");
350 check(1, 0, 0, "1");
351 check(1, 2, 0, "1.2");
352 check(1, 2, 3, "1.2.3");
353 check(9999, 99, 99, "9999.99.99");
354
355 // Check leading zeroes
356 check(10, 0, 0, "010");
357 check(10, 20, 0, "010.020");
358 check(10, 20, 30, "010.020.030");
359 check(10000, 100, 100, "000010000.00100.00100");
360
361 // Too many parts
362 assert!(parse_os_version(b"1.2.3.4").is_err());
363
364 // Empty
365 assert!(parse_os_version(b"").is_err());
366
367 // Invalid digit
368 assert!(parse_os_version(b"A.B").is_err());
369
370 // Missing digits
371 assert!(parse_os_version(b".").is_err());
372 assert!(parse_os_version(b".1").is_err());
373 assert!(parse_os_version(b"1.").is_err());
374
375 // Too large
376 assert!(parse_os_version(b"100000").is_err());
377 assert!(parse_os_version(b"1.1000").is_err());
378 assert!(parse_os_version(b"1.1.1000").is_err());
379}
library/std/src/sys/platform_version/mod.rs created+13
......@@ -0,0 +1,13 @@
1//! Runtime lookup of operating system / platform version.
2//!
3//! Related to [RFC 3750](https://github.com/rust-lang/rfcs/pull/3750), which
4//! does version detection at compile-time.
5//!
6//! See also the `os_info` crate.
7
8#[cfg(target_vendor = "apple")]
9mod darwin;
10
11// In the future, we could expand this module with:
12// - `RtlGetVersion` on Windows.
13// - `__system_property_get` on Android.
src/doc/style-guide/src/README.md+10-2
......@@ -112,6 +112,14 @@ fn bar() {}
112112fn baz() {}
113113```
114114
115### Trailing whitespace
116
117Do not include trailing whitespace on the end of any line. This includes blank
118lines, comment lines, code lines, and string literals.
119
120Note that avoiding trailing whitespace in string literals requires care to
121preserve the value of the literal.
122
115123### Sorting
116124
117125In various cases, the default Rust style specifies to sort things. If not
......@@ -225,8 +233,8 @@ newline after the opening sigil, and a newline before the closing sigil.
225233
226234Prefer to put a comment on its own line. Where a comment follows code, put a
227235single space before it. Where a block comment appears inline, use surrounding
228whitespace as if it were an identifier or keyword. Do not include trailing
229whitespace after a comment or at the end of any line in a multi-line comment.
236whitespace as if it were an identifier or keyword.
237
230238Examples:
231239
232240```rust
src/doc/unstable-book/src/compiler-flags/sanitizer.md+16-16
......@@ -244,18 +244,16 @@ See the [Clang ControlFlowIntegrity documentation][clang-cfi] for more details.
244244
245245## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination
246246
247```rust,ignore (making doc tests pass cross-platform is hard)
248use std::arch::naked_asm;
249use std::mem;
250
247```rust
251248fn add_one(x: i32) -> i32 {
252249 x + 1
253250}
254251
255252#[unsafe(naked)]
256pub extern "C" fn add_two(x: i32) {
253# #[cfg(all(target_os = "linux", target_arch = "x86_64"))]
254pub extern "sysv64" fn add_two(x: i32) {
257255 // x + 2 preceded by a landing pad/nop block
258 naked_asm!(
256 std::arch::naked_asm!(
259257 "
260258 nop
261259 nop
......@@ -281,16 +279,18 @@ fn main() {
281279
282280 println!("The answer is: {}", answer);
283281
284 println!("With CFI enabled, you should not see the next answer");
285 let f: fn(i32) -> i32 = unsafe {
286 // Offset 0 is a valid branch/call destination (i.e., the function entry
287 // point), but offsets 1-8 within the landing pad/nop block are invalid
288 // branch/call destinations (i.e., within the body of the function).
289 mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
290 };
291 let next_answer = do_twice(f, 5);
292
293 println!("The next answer is: {}", next_answer);
282# #[cfg(all(target_os = "linux", target_arch = "x86_64"))] {
283 println!("With CFI enabled, you should not see the next answer");
284 let f: fn(i32) -> i32 = unsafe {
285 // Offset 0 is a valid branch/call destination (i.e., the function entry
286 // point), but offsets 1-8 within the landing pad/nop block are invalid
287 // branch/call destinations (i.e., within the body of the function).
288 std::mem::transmute::<*const u8, fn(i32) -> i32>((add_two as *const u8).offset(5))
289 };
290 let next_answer = do_twice(f, 5);
291
292 println!("The next answer is: {}", next_answer);
293# }
294294}
295295```
296296Fig. 1. Redirecting control flow using an indirect branch/call to an invalid
src/stage0+121-121
......@@ -15,7 +15,7 @@ nightly_branch=master
1515
1616compiler_date=2025-08-05
1717compiler_version=beta
18rustfmt_date=2025-08-06
18rustfmt_date=2025-09-05
1919rustfmt_version=nightly
2020
2121dist/2025-08-05/rustc-beta-aarch64-apple-darwin.tar.gz=b9d8f74da46aeadb6c650a4ccfc3c2de08e229e4211a198fa2914103f09f579d
......@@ -396,123 +396,123 @@ dist/2025-08-05/clippy-beta-x86_64-unknown-linux-musl.tar.gz=79fd42cffac98024308
396396dist/2025-08-05/clippy-beta-x86_64-unknown-linux-musl.tar.xz=a3a616554ed25630df9f8cef37a5d36573e6f722b1f6b4220ff4885e2d3a60de
397397dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.gz=ad1849cb72ccfd52ba17a34d90f65226726e5044f7ffbe975c74f23643d87d98
398398dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.xz=608001728598164e234f176d0c6cfe7317dde27fb4cbb8ad1c2452289e83bf30
399dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.gz=b33b3bd26dd4518802b325e7c151ea73fa6844bc710ac2d2c8fb55a27c5d7e2a
400dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.xz=c900e816a94a0ddd7701c64051ba0e0244c5799e77189e26df109649b10f636f
401dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=aa7c344a52c69ee9b9e68007da806f5741688ce3917c377b6563043703e7d867
402dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=d76d7c6ca6cd5286bee12cabec166a3d8848b28a484a105b56bd5687674bc4c6
403dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=ea4d7c94a12485958b15e7a2782f9b8a09e065c021acd2894e7a905cadfa7489
404dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=4a85be8477cf4b23971fedf3b06b404cf2231f8fe941630e3e73dc902454b96e
405dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=385625349ab2e79887e2630fc861dcdd039190af36748df27500f7ea45a515f9
406dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=50cec6b681ae63ebcd60ce6cb6d328f49939c3cac1aa6b71ce76a5a3902cb52c
407dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=09a141bf2e457e91abf688c8084654e5e0b932418e351da2c0daf6cf89b77e56
408dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=7aa6d3bd020e903c842725bb3ec9dba1881f2e9cd748953c23c658ef93d49dce
409dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=c00a4b1ad60af59609e3bc61f042f9c4152de26687dcd120da173d61264b88ab
410dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=fcca5576b2f0bdab5bf7dd7ecb6ea956285aa3c129a1ea9facaf517f09f20c2d
411dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=434d9bff2e5693db416701730af1a71767715e98d674cf7273b32f76128ccab1
412dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=af48289fe813a45eb78373d80f01f060ebd2ce6337763d1ee8ea6f5080cb4eb1
413dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=68b2704b80c8f0706dc4bdba4db3b620afecbe086a7d858749d84d56f130979b
414dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=930b287659104dbf4fe759d450a4126b7a0f855fbe8fd7d3ab11aadb18ceccfa
415dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=7580ce2af926de7e07ad2313ae6397a624b10532556f7f9b9cee8ecd5addc697
416dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ed19716bdb95eb04e64299c04725c7a0b92c66121856ab891bb67a797c8b1087
417dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1d4077c7b42aabe2b80a19f3c96b457901f81667d62a5be9df617543245f0d8c
418dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e0203ce7cea0c2125d8d39d92c5137b2397115c4d99f42d0b23746d0270c78d2
419dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=0a836d9d2fc5824aeb4afd5eba709c0e3c6d4403ca8815356a0ac8735cbc95dc
420dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=f656cb9adff0aa53f47f15a937556e9b1a9418f33dff39350e48ab8c02da987a
421dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=c44a884292ffeba027d3d029d6d53ccaa2bb85787e825c9cc1dca464046a7855
422dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6992586e7dc3b95ddaa630cb61f58ec88b5d7c488aed8476be25a92d0fb4a3dd
423dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=6e053aee8964a26385292dc2e9b671995045bb736447059e536b1e7f09c79685
424dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=611d609f23f75a2b7fe304737abaf017fcf4594d9d11cbe014e91a90ee5ab27f
425dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=932f888a1a604358ad40d62bc0ca9a484f47715e8a5306fe77ae610ada4671ce
426dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=4eae3ed539b4ff8b39dae4ea4089081fa49807d31640129eec29b47030e8101e
427dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=13c65d2427c063961c19b20aa4f25bb11b3189084e2f0a798a846b95c630735b
428dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=2f8e8ec9a4c0187174a0d8d3c2addf75e68a2d60920ae100f37efb5e57a45033
429dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=e11b21d9aa403a1202c299390210d11d403501f6f55cc7ec24d6118461545825
430dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=ece7d348df665d6ff6d061e911c6bb4c9d4f161e63e888d3a66f17b533843886
431dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=d87c2370e2346587d71994ba31a0455932760507fcce680ab39322619179c429
432dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=030355ceaa2697d8b2d2de41b56cc4ef50124aa81b2f226cf0d56a1e011e0fa6
433dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=d725272b6b92059afd637a3edfc6dc2b22013bf4e70a0ed1f7c5aad3c6a71fca
434dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0c3e7de4e92f696585bd6a85c30fab337548e4393c3ec5b52832f3533acb063
435dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=79f6a3429c2ee29e1350bfce20f7f5ca1e5ec46720194cf3f34977fe446c79cd
436dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=777568cc6df1ce1b96f291027a5024109c189e83e2e2c046a3248e3a1cbedcc6
437dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=2528c1e6256bd9e73174b435802702bbe66eaaa4cff3748d3e5b7580ca7bc789
438dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=2f62d01498b57395e03ddfffc4e0b5cdf78a7fb6f5308440b8eee24637874752
439dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a9b2f612748bc7a88eced4462999c67eeba0ea46f4a73977513c34c09286b0a3
440dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.xz=a8137526bc41ab13a624aa5c9895abcc250f38776aeb690a7939baab1093f388
441dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.gz=18015624ba6cc1892d944d6f3c82e0b22fc5ff85ac074d25ad80fb4af12f0172
442dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.xz=bc0f5d324b4b807b0a378aa0e132a429c57c4773c6d9d30e9215ba835de1a0a5
443dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=de159bd0f81d54906d8020b3da80ab3319292907c3f0c9c68654f8e6ed900135
444dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=6dd48c3a64fcc0f2f99e4cc643cf82f1a7efab1921918fd37953c64125982606
445dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=8ba8c7ce8715fb378758ae8bd6c1538e538c2dfe86771db43b7903f18a384ad3
446dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=4259f65663aea76e1397c677bc286588cd4b6f8694647c738efc55e5616bc084
447dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=bfd3e1434e5b816d9d338e6c56203f58b5c1a89499ca03099d4d86b3c665f0d1
448dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6260a7487d7d3759aea9e6691ac77ee38948a538f8b973459f444f98912753e0
449dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=c10b36a6ac99d8e1de73c3ae0ca74ef10600baf7a3963f6885282b97f703f992
450dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=b8de069c788f4a6c195d7a429ed656a45ea2a9a5775138de46d79c1c3591e70e
451dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b0f0d9331d213015493e080f8cd06e6ed955693981241acd692a92dd545df66f
452dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=91ed6b2792622c68a5cc3698650860373305a39162b2b643b1c219cab6debbba
453dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=b1920a45d2532f41956b2c1112cf8c590243b1417bc48f3922056e1d62a27a1d
454dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=1825ed54530deb070d6f894cc12ca157be57a37e6d7ccc6007a51674eae42082
455dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=ac01818b1cc9130b4dcdad9db8137382655d21df9d6e7edc5cd0f84c71bbe787
456dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=21ee5aeb048e5337b3231b4f3ca8a6bfacc3a1cc23800052093d360ca22b3b78
457dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=020995d3e24b4e72b0166662fd2e6969f397baa728999bbd09bce76e5381e0b5
458dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=4a09cad2bd24ae6a15c83fb9098f66208219d3ab14c9fd46a3ce7a3c8efe6119
459dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.gz=25e5461350634cbd4b38dce96bc6ba6a9fbdb87caed51f26dfa058105bbccb4a
460dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.xz=e8774ab1e12ba4d3d088dfb0c6a929b3fb6866db035eb10a60b203a6af59f490
461dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=0094366fa4b8f33c7ec5bb75fa5116044c76f3b7bf4a96b5a48b31dbf6f080eb
462dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=6686cbf9182560d9b691ac56b3e89ed76c4fe6340dd036820a1a126e2ff41689
463dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=d3e23b1b5ac10b0cc406eb5397da7fff30aa4e558832379debf4410551ebdc4d
464dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=fd2771191a84469c6b1fcef7e90388f4699ef087e082c9838ca2bb2d1d50b399
465dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d4848e6a71e9cb6b87e46843f61da911ae81266f5c3aca10f85120d069d304bb
466dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=b1e9c97f2b1c06ebf1dc00cf5fa23191a86e3ef234ebaeeced2bd41b3e59b656
467dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=4d68bc5ecf31127f67d1bb2359e9ca475ea7a0c396da29b00781929f1f00ba6c
468dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=8588747d7ce6c5a9b68ba6805b63449695e60d2e9ea7f3f0ad5f4e5a04d9062c
469dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=4ebb3bd5e06737d2b61f249a674cda32a2a58e871039c37d49c2d6c8d2ecd6d9
470dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=5740de96cfbdcc5261e0df10e9c7ec63e28bd553f9691a8e26e6fe9f76cbbee3
471dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f4a9b5c0b6d2cf2f86feac062018e044cfbd05c9cc8243e2ff44d8196745
472dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=a1f54aab1b4a5ebc09d9b57c892072dfd8d5280fe7a0f3dd3f643ffc72992d34
473dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=cac4ed0ff044997a35471f6c291bb165b48cdcf3f0a0a4df24d7c91cbe121362
474dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=47e6083275169ef75dde6daae2bb9ca599ea03ce56d31945e9e0b42d09ebf364
475dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.gz=95c87a447d33748fbfa1e9136dfb290814a7dfb1a28efc45f14f0c7830ec49bb
476dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.xz=52929264f954609165aca5d925d6a1f0e41f78647b45edcd8a7c8c3f872c4bd7
477dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.gz=f8db463c7c5aeb7fda6d0aa2e4d460d42a7fca5ec8b9b4d8a97e4f988c72a1bd
478dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.xz=b33e23dfc673dda3eaa81d3c2d690e68cbc95bfb09864c8b2307029b0509c4f0
479dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.gz=f4f243206778a3997e3ab63170182a6e210cedd47c2a17358146e3e2cb892912
480dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.xz=194cda3450befacd2da23bccf836995f09a85e7e9c6d4ba5613cbb3c1768815f
481dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f189ae4ab931c61eef04b5748b696070b998699315629a3b95d4f0b4cdae9ff9
482dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=23c82bf0d9f5532d94a24cfaeec66fc5f02e1b28c854e5689babd41ebcfc0ad2
483dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=3e76a7201dd24f9d79589445509f0c80e6902864731f71d1da3f5343a75aa5bc
484dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=3a62df3e5497fee4e56bc428db422990c7df924f72dacb6897b3783560a967c8
485dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=cc5c126bb1ad662dc78a3b4b039e6cd32445b45b163886180fda199cbfdae9df
486dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=1c9ecfef304fb901ec6f2cfd4e170d1f02511bb2a84de664718c20c7d154e313
487dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=76b6c1025d9dc045bfdfb5e0ca8e9cde674d0c40bb67f600ecb0e765b9f71f03
488dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=bf08f2bbd2197919acfcdf8db8130882ec8f77cb41371729072e7e94cc54997b
489dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7e5e5816a18c3b22a5a5cd0814206c3cb53c7fa2ce3d36c9c045e1fac87b0747
490dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6470b0bbe1a82064de13bd9540acbd2368421e8b000cfd8af05886a48cf11d2c
491dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=1a2cfbf02e55995793bdd9cf3809ace31a3d9900667ec6d5e71c6c63af26f578
492dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=7ea6594b669fa77481ff8ec4e8cf447c11e021a412584e1e60f0baed0976316e
493dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5cbd5821ad528d90f191a17d019b71ac2beea413b00ceec78aef9433832b2469
494dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=86002592eb275d582ec8656d903ddd2247a0fcfdb2c6d90f337735a574debb9a
495dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1c420af2bb6af11b2a718ff02d96794e9916a7f538d622b418f39ecd451e1fd6
496dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=1c33f80fbc3284d8499ec03bddb5bd9ebbe7e0da1aac6675d8442a3443440c3c
497dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.gz=366a9097aaf91fd8b2853b2f94d82b8baf162dae5ef1b514072b4da19fec87a5
498dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.xz=eca0aaa16e5e7006b19e56330157545d0fb56a5e590c92e041afbc8205c35ab0
499dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.gz=f2665645f498cc57e0b6cb052715afd264b7bb3184be58d50f528562a1610111
500dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.xz=2d5dba8ed862c80035ef742d9a45c1e122228219b4e1da8fd8b920eb589bbe71
501dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.gz=6970602ef52246883c2df83795cca94356a1e978265facab3dd3f838707d31d3
502dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.xz=92e7a314326015586054cdd5044c3123f41972432b2167f0dd551ee9380d66ca
503dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=5405ac07a580ba16b0f95ed0fc56a24318e8aab7abfe04c2ed3c87f9d6f1edcb
504dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=10d189c68491e15b6dd34b7f47bf8c72ccb8ab7260c4d815cb51046fd24ad76c
505dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=812a29f858412b9c256184e8e2b3d65d0c9912d7f4157a9ba640c8231caa5160
506dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=aa22d4547d85669a17c8a475baf533614d8d0547b1e386dc11bde66f215a874c
507dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=5e60c66f60a4358c0f8b2fea5577f71f4c056c7b2d0afefd9289f782004fbc63
508dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=6d975c907e1def685c14fe6e460001af0362824f771585f9b1ccc2cc1ea71fac
509dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.gz=465206e95e2c6a7731ca55db9e576f1f78e9d356ba81c6687752793101c80b92
510dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.xz=13cd73704262a891ea825201e6583c171f7a920c1be5372b4cccf5cbe3d294fc
511dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.gz=a7bf182bf19812d41e103a8d89e6c3457c1c9d0ddd800f59fdc3d94df587e3c3
512dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.xz=43da78e7dca1415ecd756ef13fd08a8358b8deedf406d18801f36e38843a704f
513dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ef6381475d22aff666429754e25855e97a4dc39e8d508c02a0e353df58afcaba
514dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=238910ad25562d4f7fa6c83d92f9cad5ec3817191907958fa646251c9bcdb690
515dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=df2464c2f2c9233f2009ac73924e95b7dd395c8575874a3391fe2f3dfcfda327
516dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=99c5a9d7f0e7f9e3acde96bfd1d23a11100be81a3651e8267e6e0ffca6bc553d
517dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.gz=705dd37d72d99694234af13a561dd9995a0e4c2bfd888aa451b666f49a7083a7
518dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0dc9551d63131336cd97b7bfca984970fc8e5c366b39e04a179673f7859f4c1e
399dist/2025-09-05/rustfmt-nightly-aarch64-apple-darwin.tar.gz=6fd7eece7221e76c2596e0472e7311fdced87e9fab26d2a4673a3242fe779bd3
400dist/2025-09-05/rustfmt-nightly-aarch64-apple-darwin.tar.xz=1a662a55931f58be9ac05841360305f277f8b1e36f99bd0a2ee4d2cc92b7ad14
401dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=d1c3c52cf61522697d726b32ed28d7b8b4cfadf30ec57f242e8c7f9f8e09f692
402dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=2cc7cbbfa06803a2fe422ed3266f6eb519360b403c83f92259cc1b83f5ddca45
403dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=61f525d050d1ff4a29cc7240912d84c9c091f25195b58411af9ef176175a3200
404dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=504b8ace2ab7ac13be143d95ed74d94940e8706ef9f53b7778da215840337e20
405dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ff48bd98d109310638822f5813042583900e2b70edd45fccd871c7c03dd1c2e6
406dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b3de2bba7858e76cdafd326f3072e4c5b534ca9b679ea62caeffb07722e9a3c9
407dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=8ca4caedc50f09995dad7bc6e001cc863c524e28c45c186022ded589f3728709
408dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=8f2cfb052f9697052d89bb729d17d74583af3fa0be98f18a3c44ea518a8f4855
409dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=b12ac2a38b379bf0de4a92f29ca40e1955c45273e798edd1a72bd40253de70f1
410dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=87fb7185aa46f3810e09479dc8fafb66d13b41f4f40e9c4e866ea77fa47b1bb6
411dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=be1e8377f3d10f4f8a07ae06ab9f649f9d2fc9cfc395abaa5f0ad10a95c4fe7a
412dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=60646799fdacdafec9e0ed81357b5db70f85bb1241fe775e71b8ad3feb686116
413dist/2025-09-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=ed8cade9b846efb5ac121aa70ac188fbd2e61fa9402fe68c80b2cbd3ee32ccbd
414dist/2025-09-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=0d0bfbd9cd4123e0404fe476a6f16eec6e435ce28d328dc0dd0aad257b295d64
415dist/2025-09-05/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bd411db34707c36d5b60f14bba776b0b89b69d4266007a3b591c467a17ef053c
416dist/2025-09-05/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=f0f2a6a81177ae6d06ff9b8f4a5bdf3bc8b26710aaf0f09258b32f7f710722c0
417dist/2025-09-05/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=b49130da444e01fe4ef997b649aada8978b8dcca60dd38cf9e7400a7c7569e1b
418dist/2025-09-05/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=0195cdddc74cba2bf17eaa1d53edb1a2bc0e34cdf13c7b25a34ad9729a2635b8
419dist/2025-09-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=1141897495ddca10fd6d9476a624b6a340fc2bfc619148e183bcf355a0078b18
420dist/2025-09-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=81b31bc8b3d431120005c3c8eeff3ed194dd18e56220c175c3250855cbdcddbe
421dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=10a27070239e7dfcf701669c8d93ecb2d310b9fde768639a2bf5be62cd13528d
422dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=0ac4a529f4f62a94d5ae4cc8a4a52f0e7d57296ac0884258dcc5478e6b0b1785
423dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=9d0ed6778fc4f0601be1e317438cf95c414fcab6d3207c635babb4f3a6faf2b0
424dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=e40b607faf2f37c9d654cc0b60c47ea155893a3b62236cd66728f68665becb18
425dist/2025-09-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=46c029ebbfa35972b0b9e366d17c41ff8e278e01ce12634d5e3146cbf6d1a32e
426dist/2025-09-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=8d1462fd09b04a94bfb1c1841c522430b644961995bf0e19e7c8fa150628e7c7
427dist/2025-09-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=5827684ccb4d38956e77858ddeadeaff2d92905c67093207bed0f38202268151
428dist/2025-09-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=975c7d7beb5b66caed7d507aaec092fdf33de2308f4dc7de46fe74e5e15b5352
429dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=8829677ab0f898c98badf22dad61094cf53c6d599b2cc76142d3d792a44f3770
430dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3d961bead4010f8a488a065ac8a4153e3c747dfcd7d5f7eeba1cad00767a7ac5
431dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=0138c30ebe74e8ee838d9eef31c7882812bb52d2304f2de7c23c47dedd6a5032
432dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=bdb4b7b3c89a30c79f51b5fa33a2a29fc8313f8193bc43ee611e8ce7d80382d2
433dist/2025-09-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=8e440dd400bf3eb4a144318459e111069a64bb309a5a51eeb0f0383dc48ee55f
434dist/2025-09-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f623e1d7d38d94965d7653fdf4a272630b2b6dec81662fbbe5d2573f2f3f3b8f
435dist/2025-09-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=f46a8278352d5a981c6746b876fe19df3093090a866d20d24cd5cb081136b1c0
436dist/2025-09-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=fdf8b44c6f110a33ad7f969e651ad396c880a85545aadfee8a24ca3cbed35974
437dist/2025-09-05/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=59d778dea354867d64c809b40443ca0762c685dd0e5361971daab04aa7c5a5ad
438dist/2025-09-05/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=18628b2888d77281fc9b2ac5636ce4ec444ab0e47bbe0e8a08238f90040c20a3
439dist/2025-09-05/rustfmt-nightly-x86_64-apple-darwin.tar.gz=169d9f2ee4a0c726040f4940370d1162502aa6568a0a442c92cad3fbc7bd95c2
440dist/2025-09-05/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7f955cfa1ab07819f31cd904b0a79c67cae70090aabc7dafffdc1f3f67463248
441dist/2025-09-05/rustfmt-nightly-x86_64-pc-solaris.tar.gz=d2cc32d6be1d0f1a8654400f0418d16e789b62db3fbc0cca0d0d492615bcf6e2
442dist/2025-09-05/rustfmt-nightly-x86_64-pc-solaris.tar.xz=3dbc29c923a6a2809a8ef561d2ad375211b09dcb107bceabbf510ab0d7b471f0
443dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=d9b4ca2abf1062e888b31f31f517ccc6b451bd2bfdae915ec3984bc88a8be91a
444dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=00c6d92b6e82ae58e682e72c974f2dcc865820567ba44ed008e4759dfdbdca87
445dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=e75424d0aece8d548b2c9d896291288615d08ff2a37f1c4844a70839c612e633
446dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=cce9578d9b35bd8192a26e2dc7d7f7e7d5b9f08c7d73b3f4dde08208b448b063
447dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=ac4282e06b0972033f974c63d2c6cbf194d4e66a1c811f443d3fa0b886868825
448dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=a2465b31855861d0e0eea072bb366480acf2bafdd7fdfdab79c809d8bbf8d8e4
449dist/2025-09-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=30c22a97066a5711f207c1919a1d74a328540da0d9d6f85a0cc044174049c927
450dist/2025-09-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=40987da0b665940f9c406cfbb4889dc101d73846730b0bdfa1382d051297ad08
451dist/2025-09-05/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=443ba10092122fbba9854abb4aa9d2e71d8e5e65b99fae6dd572909bf50f28c5
452dist/2025-09-05/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=10285942b9140efc9897965cb3a4204145e774bd1b0c2690d45d8b04498fb917
453dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=b09af4fe367df416bce622654d9e3dfb610c564f5e6d14b200d949340595673c
454dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=1f9a585a017cee5a05190377cab105603f039fbefd9b4934278dc555dfca91b0
455dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=24f911745fcc9f120e44acccb98f54dc6406e492915410aae17efdd00e2752c3
456dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=48eb58ba1d58701dbff341e19fb6d446ed937cc410207b35297babafa29dd889
457dist/2025-09-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=c2d1cfdcd8a08bde3f9a635eaf2d6d2fbd82e4cabbbd459e3c47e64bf1581f11
458dist/2025-09-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=ed1775b4fd3d7d1203f8749f70328ea4ade802fa0a76c4d7ab3e2d63ca1535af
459dist/2025-09-05/rustc-nightly-aarch64-apple-darwin.tar.gz=4b64c4148e5cdd6585a4200125cc394c6a998da3686ef758f37742ec2d33d573
460dist/2025-09-05/rustc-nightly-aarch64-apple-darwin.tar.xz=fd45182f9db059bdc17f2c465dbaae22589eb8e8d2d88776437a34ddca3b7153
461dist/2025-09-05/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=c14f2d7f391492d150f2f2f91af413266649cbdbdb042fc8b660b3cb141b80c7
462dist/2025-09-05/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=d72ea1c571fe2376ef05cfd15fb3207ee2d27c3c851f3391dfbb082c06a5bdd0
463dist/2025-09-05/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=3a485d8fd8d58fdfbc1216e51414aa4d90f0c7285a99abea0fa5935d2337251b
464dist/2025-09-05/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=7317060a29eecd2e28d47f0ff8780150059756b07e2bc9137c3877be8af593b7
465dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=58a53ae147de1beb0a53629898bf7c51097351271be3713a2e2344b86a4080a4
466dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=f79d2730843dbea9e9588fd1c1b0d854441969d8f93f76021f06af2efe22b845
467dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=eddf23e28b8067021e80883faf2eb1d6d3005a6e8419a1232b84236bea286f78
468dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=4f0af1a66050f5e2d9d48b696349b9ccd420bdcfdb88b251a6655cc22a11949b
469dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=fd2f0446e3c993d746e8a5f72ccebd8b0a49172316ac1d1c58bad10596becbf3
470dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=0b06e7ba47621819b4e59e048e5d336b3d6978e906c7363f06bbc804e49f1046
471dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=97d7c34b53628f28e6636fae738a18d0f1f4c60a9febddfb7145e6b91fcf3fdc
472dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=323025215bf851024a7eb6566ad7dc5719832d81e8d46e70adaece98adc5644b
473dist/2025-09-05/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=3017e03222d030448ffe2805624143540197bd6d3b3e93f9f73469ace25ae4be
474dist/2025-09-05/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=4f6e86b185fb54f7a0b7d09a0faae7daac722351354f6abebd388efb3037dfa0
475dist/2025-09-05/rustc-nightly-i686-pc-windows-gnu.tar.gz=292c3770b96cde97072d70c58234488f955ed5582b7c3044c6de66891e73d639
476dist/2025-09-05/rustc-nightly-i686-pc-windows-gnu.tar.xz=6855d3fd9040fb4da554fd732eaf8a1c723921c35bb8a8efb31c78af69b2e4ec
477dist/2025-09-05/rustc-nightly-i686-pc-windows-msvc.tar.gz=64a86a2971ed9934bbb6aaa0afc2a7f747da463afb55b51a7c5fdbdaa294e437
478dist/2025-09-05/rustc-nightly-i686-pc-windows-msvc.tar.xz=c98f1fc3e077b8c8eb3e526c416a6551c08c62e58be57b4a4c7d59670bc435f9
479dist/2025-09-05/rustc-nightly-i686-unknown-linux-gnu.tar.gz=5481c97d788899f896473380dde0877808489bc4a0ed6d98265558631fa67a57
480dist/2025-09-05/rustc-nightly-i686-unknown-linux-gnu.tar.xz=afadaae945c0b9a8b50dbdee28791e0c03c880cb22d3c20996eeb7fab94df0bf
481dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=18b276a2464b6c5a817d72384f25442c7619cac05b2d8d0af212c0dad96ccfc6
482dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=b74323cd2dbee966eebe8e63e24fae026ecd900a025e9167cca0341e50333cc3
483dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=916dc5144107d9173479b320b55b0a95d2d42156c69fbdb0f21377d825fe0892
484dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=3a83da72aa4a6553ecd957af35a05274528dc79f87d24d8470c20b8b4478b05b
485dist/2025-09-05/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=59e031b6b79a1f11406c0640e1a357f2941967ea8c034a94148d60928038e58e
486dist/2025-09-05/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=53f0e33cf2651d5dc8931ec5af8f04994188d8f9a10a5c61bd72cc822df34501
487dist/2025-09-05/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=0eec56e3b725d918cb21e494a803b2e38eb6d744f64f1a82481a4c704eb7c1f0
488dist/2025-09-05/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5efc97abb235f349c6cc952b4a1e4dae7d56d70b0f8b8da2a1060b85f9b734fd
489dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=cb45bbcdf8841b1ac184a0aacc909f153c830e8051260e09ca4e32c1f048e2fb
490dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=1c9ddddb90d45612e4fd190fb71e527b523df13146343dde200580fb2b638794
491dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=3a9bdd4d14e8f121d3051944ee83a901b5ca4c0921f2d01e34596fb7450b49e3
492dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=732b9abb8a80191884fe1ff1d4d923cc1b74c21b81e6327bc5979ae526337400
493dist/2025-09-05/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=1826e74200fe286478e1659ab88ea86b43efa7b023074d00dbc814d80bebc883
494dist/2025-09-05/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c30b52d0f474fd6193bb1b3e147fb79fa8cc31e5db38444f023d84d1c2d93d12
495dist/2025-09-05/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=c330067621ed25d8383f27e494346eca4d7d4866e48f331f2ec897ff1c386e56
496dist/2025-09-05/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb4097ea582a83a94cab80ff2f36b6f7141c140d75c30b1d261a1ddd4ea45bd4
497dist/2025-09-05/rustc-nightly-sparcv9-sun-solaris.tar.gz=0af19e764f10333017a3ab66020b82c7185ad648d1230b68f10977e0affb937f
498dist/2025-09-05/rustc-nightly-sparcv9-sun-solaris.tar.xz=a22cfb55cdd122dd99bf3566eabd781bb2ecded90c71a41fd33b1e0588bcc39c
499dist/2025-09-05/rustc-nightly-x86_64-apple-darwin.tar.gz=163a07b91e36e85c6c41368598793667414cdc6cadc980866811234539f3aec3
500dist/2025-09-05/rustc-nightly-x86_64-apple-darwin.tar.xz=76711800685b39b3b75945395682062c40efe3195f9979784bf318837e21768a
501dist/2025-09-05/rustc-nightly-x86_64-pc-solaris.tar.gz=69142a6c04703c3c8309c6fdf66b25831bf9efa3ee70cc93da4b5b75f901b29a
502dist/2025-09-05/rustc-nightly-x86_64-pc-solaris.tar.xz=7e535f4aa136284e4bdfd4d56891caac6844dab91e1b711fa3914a5974dfcb60
503dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ff0ea563126ff28df297258001d9fac4dbd85788b5d27a0f5d6be75306f21139
504dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=6b66adcaa9a5332979591464242423897f59276e9e2cbeb9ab038a72e72c3a5c
505dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=64cac5e377bc115a8f8176719575903e695337941db43cfb35546d65c0723130
506dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=11e2765e4b3e2296ea05ecf735cf7b5f7beb08d76d12449cfae67f88bab02819
507dist/2025-09-05/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=c7d15ae7cd5af774ae70e63fec3ba8723b85fa4c4640917b3960907eedb30b39
508dist/2025-09-05/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=55036567af270cdac046fb4306e515787ca6ef5073617311fac79fb87ffe9366
509dist/2025-09-05/rustc-nightly-x86_64-unknown-freebsd.tar.gz=2d24470d2bb4c4d2605c15f1b2654cc45805384babb73b1960e8aea0b8cc227d
510dist/2025-09-05/rustc-nightly-x86_64-unknown-freebsd.tar.xz=fa41782cb2e22aba30d1619db1f478c0305944ceb4de1d1001f221c5c68c104e
511dist/2025-09-05/rustc-nightly-x86_64-unknown-illumos.tar.gz=d0f9785f76c59f3a67a499cfff4a5639f3ae05cbc76750b867faaa60b7d67f78
512dist/2025-09-05/rustc-nightly-x86_64-unknown-illumos.tar.xz=925e473c6e31d8811879a805358cfd2e5ab8f4de836c270d02dc8403771bed3a
513dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ebac845114b89dfe7d0efc0cfe8820902faad617ed21eb2a701d73cf7b544a85
514dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=2512a5462e3f46c95ed4aba4228282a357b3e0694e9db117a857196448fe7bcc
515dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b4a5d364b84464e9a92140fff50349d4942b8d970b64150a4bc6d720cc6c4a4e
516dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=6c57c2edc305737530f8551d789ee79ff952f42a0d52d6f8d7d7f1ea2027cfca
517dist/2025-09-05/rustc-nightly-x86_64-unknown-netbsd.tar.gz=f3192ded327875d5a27fb50c690e3fce36669e8f71c47de304dc21edad573ff9
518dist/2025-09-05/rustc-nightly-x86_64-unknown-netbsd.tar.xz=11359e4731866f6a788e5699867e45befdf1ad49ef35c0aba22af76d3f327cc3
src/tools/tidy/src/extra_checks/mod.rs+1-1
......@@ -303,7 +303,7 @@ fn check_impl(
303303 }
304304
305305 if js_lint {
306 rustdoc_js::lint(outdir, librustdoc_path, tools_path)?;
306 rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless)?;
307307 rustdoc_js::es_check(outdir, librustdoc_path)?;
308308 }
309309
src/tools/tidy/src/extra_checks/rustdoc_js.rs+21-9
......@@ -40,13 +40,18 @@ fn rustdoc_js_files(librustdoc_path: &Path) -> Vec<PathBuf> {
4040 return files;
4141}
4242
43fn run_eslint(outdir: &Path, args: &[PathBuf], config_folder: PathBuf) -> Result<(), super::Error> {
44 let mut child = spawn_cmd(
45 Command::new(node_module_bin(outdir, "eslint"))
46 .arg("-c")
47 .arg(config_folder.join(".eslintrc.js"))
48 .args(args),
49 )?;
43fn run_eslint(
44 outdir: &Path,
45 args: &[PathBuf],
46 config_folder: PathBuf,
47 bless: bool,
48) -> Result<(), super::Error> {
49 let mut cmd = Command::new(node_module_bin(outdir, "eslint"));
50 if bless {
51 cmd.arg("--fix");
52 }
53 cmd.arg("-c").arg(config_folder.join(".eslintrc.js")).args(args);
54 let mut child = spawn_cmd(&mut cmd)?;
5055 match child.wait() {
5156 Ok(exit_status) => {
5257 if exit_status.success() {
......@@ -62,16 +67,23 @@ pub(super) fn lint(
6267 outdir: &Path,
6368 librustdoc_path: &Path,
6469 tools_path: &Path,
70 bless: bool,
6571) -> Result<(), super::Error> {
6672 let files_to_check = rustdoc_js_files(librustdoc_path);
6773 println!("Running eslint on rustdoc JS files");
68 run_eslint(outdir, &files_to_check, librustdoc_path.join("html/static"))?;
74 run_eslint(outdir, &files_to_check, librustdoc_path.join("html/static"), bless)?;
6975
70 run_eslint(outdir, &[tools_path.join("rustdoc-js/tester.js")], tools_path.join("rustdoc-js"))?;
76 run_eslint(
77 outdir,
78 &[tools_path.join("rustdoc-js/tester.js")],
79 tools_path.join("rustdoc-js"),
80 bless,
81 )?;
7182 run_eslint(
7283 outdir,
7384 &[tools_path.join("rustdoc-gui/tester.js")],
7485 tools_path.join("rustdoc-gui"),
86 bless,
7587 )?;
7688 Ok(())
7789}
src/tools/unicode-table-generator/src/main.rs+1-1
......@@ -228,7 +228,7 @@ fn main() {
228228
229229 let mut table_file = String::new();
230230 table_file.push_str(
231 "///! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!\n",
231 "//! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually!\n",
232232 );
233233
234234 let mut total_bytes = 0;
tests/run-make/apple-c-available-links/foo.c created+22
......@@ -0,0 +1,22 @@
1int foo(void) {
2 // Act as if using some API that's a lot newer than the deployment target.
3 //
4 // This forces Clang to insert a call to __isPlatformVersionAtLeast,
5 // and linking will fail if that is not present.
6 if (__builtin_available(
7 macos 1000.0,
8 ios 1000.0,
9 tvos 1000.0,
10 watchos 1000.0,
11 // CI runs below Xcode 15, where `visionos` wasn't a valid key in
12 // `__builtin_available`.
13#ifdef TARGET_OS_VISION
14 visionos 1000.0,
15#endif
16 *
17 )) {
18 return 1;
19 } else {
20 return 0;
21 }
22}
tests/run-make/apple-c-available-links/main.rs created+7
......@@ -0,0 +1,7 @@
1unsafe extern "C" {
2 safe fn foo() -> core::ffi::c_int;
3}
4
5fn main() {
6 assert_eq!(foo(), 0);
7}
tests/run-make/apple-c-available-links/rmake.rs created+14
......@@ -0,0 +1,14 @@
1//! Test that using `__builtin_available` in C (`@available` in Objective-C)
2//! successfully links (because `std` provides the required symbols).
3
4//@ only-apple __builtin_available is (mostly) specific to Apple platforms.
5
6use run_make_support::{cc, rustc, target};
7
8fn main() {
9 // Invoke the C compiler to generate an object file.
10 cc().arg("-c").input("foo.c").output("foo.o").run();
11
12 // Link the object file together with a Rust program.
13 rustc().target(target()).input("main.rs").link_arg("foo.o").run();
14}
tests/rustdoc-gui/scrape-examples-ice-links.goml+2
......@@ -4,3 +4,5 @@ wait-for: ".scraped-example-title"
44assert-attribute: (".scraped-example-title a", {"href": "../src/bar/bar.rs.html#2"})
55click: ".scraped-example-title a"
66wait-for-property: ("h1", {"innerText": "bar/\nbar.rs"})
7// Ensure that the `--html-after-content` option was correctly handled.
8assert: "#outer-html"
tests/rustdoc-gui/src/scrape_examples_ice/empty.html deleted-1
......@@ -1 +0,0 @@
1
tests/rustdoc-gui/src/scrape_examples_ice/extra.html created+1
......@@ -0,0 +1 @@
1<span id="outer-html"></span>
tests/rustdoc-gui/src/scrape_examples_ice/src/lib.rs+1-1
......@@ -1,5 +1,5 @@
11//@ run-flags:-Zrustdoc-scrape-examples
2//@ compile-flags: --html-after-content empty.html
2//@ compile-flags: --html-after-content extra.html
33pub struct ObscurelyNamedType1;
44
55impl ObscurelyNamedType1 {
triagebot.toml+1
......@@ -380,6 +380,7 @@ trigger_files = [
380380[autolabel."O-apple"]
381381trigger_files = [
382382 "library/std/src/os/darwin",
383 "library/std/src/sys/platform_version/darwin",
383384 "library/std/src/sys/sync/thread_parking/darwin.rs",
384385 "compiler/rustc_target/src/spec/base/apple",
385386]