| author | bors <bors@rust-lang.org> 2025-09-05 20:49:13 UTC |
| committer | bors <bors@rust-lang.org> 2025-09-05 20:49:13 UTC |
| log | 6c699a37235700ab749e3f14147fe41d49c056e8 |
| tree | 0f9a359fdd990ba03da8f8aa6ba4ca82682dbda5 |
| parent | 99317ef14d0be42fa4039eea7c5ce50cb4e9aee7 |
| parent | 55a62d57ed85c8e1cd412c368c72fc2e7dad48f5 |
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: rollup34 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 |
| 296 | 296 | .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu)) |
| 297 | 297 | } |
| 298 | 298 | |
| 299 | /// Get the `target-features` LLVM attribute. | |
| 300 | pub(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 | ||
| 299 | 312 | /// Get the `NonLazyBind` LLVM attribute, |
| 300 | 313 | /// if the codegen options allow skipping the PLT. |
| 301 | 314 | pub(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>( |
| 523 | 536 | } |
| 524 | 537 | } |
| 525 | 538 | |
| 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)); | |
| 534 | 540 | |
| 535 | 541 | attributes::apply_to_llfn(llfn, Function, &to_add); |
| 536 | 542 | } |
compiler/rustc_codegen_llvm/src/context.rs+8-2| ... | ... | @@ -853,7 +853,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
| 853 | 853 | fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> { |
| 854 | 854 | let entry_name = self.sess().target.entry_name.as_ref(); |
| 855 | 855 | if self.get_declared_value(entry_name).is_none() { |
| 856 | Some(self.declare_entry_fn( | |
| 856 | let llfn = self.declare_entry_fn( | |
| 857 | 857 | entry_name, |
| 858 | 858 | llvm::CallConv::from_conv( |
| 859 | 859 | self.sess().target.entry_abi, |
| ... | ... | @@ -861,7 +861,13 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
| 861 | 861 | ), |
| 862 | 862 | llvm::UnnamedAddr::Global, |
| 863 | 863 | 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) | |
| 865 | 871 | } else { |
| 866 | 872 | // If the symbol already exists, it is an error: for example, the user wrote |
| 867 | 873 | // #[no_mangle] extern "C" fn main(..) {..} |
compiler/rustc_codegen_ssa/src/lib.rs+1-1| ... | ... | @@ -119,7 +119,7 @@ impl<M> ModuleCodegen<M> { |
| 119 | 119 | }); |
| 120 | 120 | |
| 121 | 121 | CompiledModule { |
| 122 | name: self.name.clone(), | |
| 122 | name: self.name, | |
| 123 | 123 | object, |
| 124 | 124 | dwarf_object, |
| 125 | 125 | 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. | |
| 2 | 2 | use rustc_hir::def_id::DefId; |
| 3 | 3 | use rustc_middle::traits::ObligationCause; |
| 4 | 4 | use rustc_middle::ty::relate::RelateResult; |
compiler/rustc_mir_transform/src/coverage/expansion.rs+1-1| ... | ... | @@ -82,7 +82,7 @@ impl ExpnNode { |
| 82 | 82 | Self { |
| 83 | 83 | expn_id, |
| 84 | 84 | |
| 85 | expn_kind: expn_data.kind.clone(), | |
| 85 | expn_kind: expn_data.kind, | |
| 86 | 86 | call_site, |
| 87 | 87 | call_site_expn_id, |
| 88 | 88 |
compiler/rustc_resolve/src/late/diagnostics.rs+1-1| ... | ... | @@ -3099,7 +3099,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { |
| 3099 | 3099 | |err, _, span, message, suggestion, span_suggs| { |
| 3100 | 3100 | err.multipart_suggestion_verbose( |
| 3101 | 3101 | message, |
| 3102 | std::iter::once((span, suggestion)).chain(span_suggs.clone()).collect(), | |
| 3102 | std::iter::once((span, suggestion)).chain(span_suggs).collect(), | |
| 3103 | 3103 | Applicability::MaybeIncorrect, |
| 3104 | 3104 | ); |
| 3105 | 3105 | true |
compiler/rustc_symbol_mangling/src/v0.rs+6-2| ... | ... | @@ -82,9 +82,13 @@ pub(super) fn mangle<'tcx>( |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String { |
| 85 | if item_name == "rust_eh_personality" { | |
| 85 | match item_name { | |
| 86 | 86 | // 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 | _ => {} | |
| 88 | 92 | } |
| 89 | 93 | |
| 90 | 94 | 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> { |
| 318 | 318 | let (expected, found) = if expected_str == found_str { |
| 319 | 319 | (join_path_syms(&expected_abs), join_path_syms(&found_abs)) |
| 320 | 320 | } else { |
| 321 | (expected_str.clone(), found_str.clone()) | |
| 321 | (expected_str, found_str) | |
| 322 | 322 | }; |
| 323 | 323 | |
| 324 | 324 | // 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 { |
| 832 | 832 | #[unstable(feature = "f128", issue = "116909")] |
| 833 | 833 | #[rustc_const_unstable(feature = "f128", issue = "116909")] |
| 834 | 834 | pub const fn midpoint(self, other: f128) -> f128 { |
| 835 | const LO: f128 = f128::MIN_POSITIVE * 2.; | |
| 836 | 835 | const HI: f128 = f128::MAX / 2.; |
| 837 | 836 | |
| 838 | 837 | let (a, b) = (self, other); |
| ... | ... | @@ -842,14 +841,7 @@ impl f128 { |
| 842 | 841 | if abs_a <= HI && abs_b <= HI { |
| 843 | 842 | // Overflow is impossible |
| 844 | 843 | (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 | |
| 851 | 844 | } else { |
| 852 | // Safe to halve `a` and `b` | |
| 853 | 845 | (a / 2.) + (b / 2.) |
| 854 | 846 | } |
| 855 | 847 | } |
library/core/src/num/f16.rs-8| ... | ... | @@ -820,7 +820,6 @@ impl f16 { |
| 820 | 820 | #[unstable(feature = "f16", issue = "116909")] |
| 821 | 821 | #[rustc_const_unstable(feature = "f16", issue = "116909")] |
| 822 | 822 | pub const fn midpoint(self, other: f16) -> f16 { |
| 823 | const LO: f16 = f16::MIN_POSITIVE * 2.; | |
| 824 | 823 | const HI: f16 = f16::MAX / 2.; |
| 825 | 824 | |
| 826 | 825 | let (a, b) = (self, other); |
| ... | ... | @@ -830,14 +829,7 @@ impl f16 { |
| 830 | 829 | if abs_a <= HI && abs_b <= HI { |
| 831 | 830 | // Overflow is impossible |
| 832 | 831 | (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 | |
| 839 | 832 | } else { |
| 840 | // Safe to halve `a` and `b` | |
| 841 | 833 | (a / 2.) + (b / 2.) |
| 842 | 834 | } |
| 843 | 835 | } |
library/core/src/num/f32.rs-8| ... | ... | @@ -1025,7 +1025,6 @@ impl f32 { |
| 1025 | 1025 | ((self as f64 + other as f64) / 2.0) as f32 |
| 1026 | 1026 | } |
| 1027 | 1027 | _ => { |
| 1028 | const LO: f32 = f32::MIN_POSITIVE * 2.; | |
| 1029 | 1028 | const HI: f32 = f32::MAX / 2.; |
| 1030 | 1029 | |
| 1031 | 1030 | let (a, b) = (self, other); |
| ... | ... | @@ -1035,14 +1034,7 @@ impl f32 { |
| 1035 | 1034 | if abs_a <= HI && abs_b <= HI { |
| 1036 | 1035 | // Overflow is impossible |
| 1037 | 1036 | (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 | |
| 1044 | 1037 | } else { |
| 1045 | // Safe to halve `a` and `b` | |
| 1046 | 1038 | (a / 2.) + (b / 2.) |
| 1047 | 1039 | } |
| 1048 | 1040 | } |
library/core/src/num/f64.rs-8| ... | ... | @@ -1026,7 +1026,6 @@ impl f64 { |
| 1026 | 1026 | #[stable(feature = "num_midpoint", since = "1.85.0")] |
| 1027 | 1027 | #[rustc_const_stable(feature = "num_midpoint", since = "1.85.0")] |
| 1028 | 1028 | pub const fn midpoint(self, other: f64) -> f64 { |
| 1029 | const LO: f64 = f64::MIN_POSITIVE * 2.; | |
| 1030 | 1029 | const HI: f64 = f64::MAX / 2.; |
| 1031 | 1030 | |
| 1032 | 1031 | let (a, b) = (self, other); |
| ... | ... | @@ -1036,14 +1035,7 @@ impl f64 { |
| 1036 | 1035 | if abs_a <= HI && abs_b <= HI { |
| 1037 | 1036 | // Overflow is impossible |
| 1038 | 1037 | (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 | |
| 1045 | 1038 | } else { |
| 1046 | // Safe to halve `a` and `b` | |
| 1047 | 1039 | (a / 2.) + (b / 2.) |
| 1048 | 1040 | } |
| 1049 | 1041 | } |
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! | |
| 2 | 2 | // Alphabetic : 1727 bytes, 142759 codepoints in 757 ranges (U+000041 - U+0323B0) using skiplist |
| 3 | 3 | // Case_Ignorable : 1053 bytes, 2749 codepoints in 452 ranges (U+000027 - U+0E01F0) using skiplist |
| 4 | 4 | // Cased : 407 bytes, 4578 codepoints in 159 ranges (U+000041 - U+01F18A) using skiplist |
library/std/src/lib.rs+2| ... | ... | @@ -354,6 +354,7 @@ |
| 354 | 354 | #![feature(hasher_prefixfree_extras)] |
| 355 | 355 | #![feature(hashmap_internals)] |
| 356 | 356 | #![feature(hint_must_use)] |
| 357 | #![feature(int_from_ascii)] | |
| 357 | 358 | #![feature(ip)] |
| 358 | 359 | #![feature(lazy_get)] |
| 359 | 360 | #![feature(maybe_uninit_slice)] |
| ... | ... | @@ -369,6 +370,7 @@ |
| 369 | 370 | #![feature(slice_internals)] |
| 370 | 371 | #![feature(slice_ptr_get)] |
| 371 | 372 | #![feature(slice_range)] |
| 373 | #![feature(slice_split_once)] | |
| 372 | 374 | #![feature(std_internals)] |
| 373 | 375 | #![feature(str_internals)] |
| 374 | 376 | #![feature(sync_unsafe_cell)] |
library/std/src/sys/mod.rs+1| ... | ... | @@ -26,6 +26,7 @@ pub mod io; |
| 26 | 26 | pub mod net; |
| 27 | 27 | pub mod os_str; |
| 28 | 28 | pub mod path; |
| 29 | pub mod platform_version; | |
| 29 | 30 | pub mod process; |
| 30 | 31 | pub mod random; |
| 31 | 32 | pub 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)] | |
| 3 | use super::root_relative; | |
| 4 | use crate::ffi::{CStr, c_char, c_void}; | |
| 5 | use crate::ptr::null_mut; | |
| 6 | use crate::sys::common::small_c_string::run_path_with_cstr; | |
| 7 | ||
| 8 | // MacTypes.h | |
| 9 | pub(super) type Boolean = u8; | |
| 10 | // CoreFoundation/CFBase.h | |
| 11 | pub(super) type CFTypeID = usize; | |
| 12 | pub(super) type CFOptionFlags = usize; | |
| 13 | pub(super) type CFIndex = isize; | |
| 14 | pub(super) type CFTypeRef = *mut c_void; | |
| 15 | pub(super) type CFAllocatorRef = CFTypeRef; | |
| 16 | pub(super) const kCFAllocatorDefault: CFAllocatorRef = null_mut(); | |
| 17 | // CoreFoundation/CFError.h | |
| 18 | pub(super) type CFErrorRef = CFTypeRef; | |
| 19 | // CoreFoundation/CFData.h | |
| 20 | pub(super) type CFDataRef = CFTypeRef; | |
| 21 | // CoreFoundation/CFPropertyList.h | |
| 22 | pub(super) const kCFPropertyListImmutable: CFOptionFlags = 0; | |
| 23 | pub(super) type CFPropertyListFormat = CFIndex; | |
| 24 | pub(super) type CFPropertyListRef = CFTypeRef; | |
| 25 | // CoreFoundation/CFString.h | |
| 26 | pub(super) type CFStringRef = CFTypeRef; | |
| 27 | pub(super) type CFStringEncoding = u32; | |
| 28 | pub(super) const kCFStringEncodingUTF8: CFStringEncoding = 0x08000100; | |
| 29 | // CoreFoundation/CFDictionary.h | |
| 30 | pub(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`. | |
| 40 | pub(super) struct CFHandle(*mut c_void); | |
| 41 | ||
| 42 | macro_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 | ||
| 73 | impl 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 | ||
| 174 | impl 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 @@ |
| 1 | use self::core_foundation::{ | |
| 2 | CFDictionaryRef, CFHandle, CFIndex, CFStringRef, CFTypeRef, kCFAllocatorDefault, | |
| 3 | kCFPropertyListImmutable, kCFStringEncodingUTF8, | |
| 4 | }; | |
| 5 | use crate::borrow::Cow; | |
| 6 | use crate::bstr::ByteStr; | |
| 7 | use crate::ffi::{CStr, c_char}; | |
| 8 | use crate::num::{NonZero, ParseIntError}; | |
| 9 | use crate::path::{Path, PathBuf}; | |
| 10 | use crate::ptr::null_mut; | |
| 11 | use crate::sync::atomic::{AtomicU32, Ordering}; | |
| 12 | use crate::{env, fs}; | |
| 13 | ||
| 14 | mod core_foundation; | |
| 15 | mod public_extern; | |
| 16 | #[cfg(test)] | |
| 17 | mod 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`. | |
| 22 | type 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] | |
| 28 | const 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] | |
| 37 | fn 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] | |
| 64 | fn 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. | |
| 98 | extern "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`. | |
| 110 | fn 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. | |
| 197 | fn 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. | |
| 208 | fn 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`]. | |
| 259 | unsafe 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". | |
| 314 | fn 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. | |
| 332 | fn 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 | ||
| 345 | struct Deferred<F: FnMut()>(F); | |
| 346 | ||
| 347 | impl<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 | ||
| 62 | use 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. | |
| 84 | pub(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] | |
| 148 | pub(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 @@ |
| 1 | use super::public_extern::*; | |
| 2 | use super::*; | |
| 3 | use crate::process::Command; | |
| 4 | ||
| 5 | #[test] | |
| 6 | fn 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] | |
| 14 | fn 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")] | |
| 21 | fn 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] | |
| 49 | fn 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] | |
| 56 | fn 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] | |
| 67 | fn 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"] | |
| 312 | fn 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 | )] | |
| 326 | fn 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] | |
| 339 | fn 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")] | |
| 9 | mod 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() {} |
| 112 | 112 | fn baz() {} |
| 113 | 113 | ``` |
| 114 | 114 | |
| 115 | ### Trailing whitespace | |
| 116 | ||
| 117 | Do not include trailing whitespace on the end of any line. This includes blank | |
| 118 | lines, comment lines, code lines, and string literals. | |
| 119 | ||
| 120 | Note that avoiding trailing whitespace in string literals requires care to | |
| 121 | preserve the value of the literal. | |
| 122 | ||
| 115 | 123 | ### Sorting |
| 116 | 124 | |
| 117 | 125 | In 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. |
| 225 | 233 | |
| 226 | 234 | Prefer to put a comment on its own line. Where a comment follows code, put a |
| 227 | 235 | single space before it. Where a block comment appears inline, use surrounding |
| 228 | whitespace as if it were an identifier or keyword. Do not include trailing | |
| 229 | whitespace after a comment or at the end of any line in a multi-line comment. | |
| 236 | whitespace as if it were an identifier or keyword. | |
| 237 | ||
| 230 | 238 | Examples: |
| 231 | 239 | |
| 232 | 240 | ```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. |
| 244 | 244 | |
| 245 | 245 | ## Example 1: Redirecting control flow using an indirect branch/call to an invalid destination |
| 246 | 246 | |
| 247 | ```rust,ignore (making doc tests pass cross-platform is hard) | |
| 248 | use std::arch::naked_asm; | |
| 249 | use std::mem; | |
| 250 | ||
| 247 | ```rust | |
| 251 | 248 | fn add_one(x: i32) -> i32 { |
| 252 | 249 | x + 1 |
| 253 | 250 | } |
| 254 | 251 | |
| 255 | 252 | #[unsafe(naked)] |
| 256 | pub extern "C" fn add_two(x: i32) { | |
| 253 | # #[cfg(all(target_os = "linux", target_arch = "x86_64"))] | |
| 254 | pub extern "sysv64" fn add_two(x: i32) { | |
| 257 | 255 | // x + 2 preceded by a landing pad/nop block |
| 258 | naked_asm!( | |
| 256 | std::arch::naked_asm!( | |
| 259 | 257 | " |
| 260 | 258 | nop |
| 261 | 259 | nop |
| ... | ... | @@ -281,16 +279,18 @@ fn main() { |
| 281 | 279 | |
| 282 | 280 | println!("The answer is: {}", answer); |
| 283 | 281 | |
| 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 | # } | |
| 294 | 294 | } |
| 295 | 295 | ``` |
| 296 | 296 | Fig. 1. Redirecting control flow using an indirect branch/call to an invalid |
src/stage0+121-121| ... | ... | @@ -15,7 +15,7 @@ nightly_branch=master |
| 15 | 15 | |
| 16 | 16 | compiler_date=2025-08-05 |
| 17 | 17 | compiler_version=beta |
| 18 | rustfmt_date=2025-08-06 | |
| 18 | rustfmt_date=2025-09-05 | |
| 19 | 19 | rustfmt_version=nightly |
| 20 | 20 | |
| 21 | 21 | dist/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 |
| 396 | 396 | dist/2025-08-05/clippy-beta-x86_64-unknown-linux-musl.tar.xz=a3a616554ed25630df9f8cef37a5d36573e6f722b1f6b4220ff4885e2d3a60de |
| 397 | 397 | dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.gz=ad1849cb72ccfd52ba17a34d90f65226726e5044f7ffbe975c74f23643d87d98 |
| 398 | 398 | dist/2025-08-05/clippy-beta-x86_64-unknown-netbsd.tar.xz=608001728598164e234f176d0c6cfe7317dde27fb4cbb8ad1c2452289e83bf30 |
| 399 | dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.gz=b33b3bd26dd4518802b325e7c151ea73fa6844bc710ac2d2c8fb55a27c5d7e2a | |
| 400 | dist/2025-08-06/rustfmt-nightly-aarch64-apple-darwin.tar.xz=c900e816a94a0ddd7701c64051ba0e0244c5799e77189e26df109649b10f636f | |
| 401 | dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=aa7c344a52c69ee9b9e68007da806f5741688ce3917c377b6563043703e7d867 | |
| 402 | dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=d76d7c6ca6cd5286bee12cabec166a3d8848b28a484a105b56bd5687674bc4c6 | |
| 403 | dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=ea4d7c94a12485958b15e7a2782f9b8a09e065c021acd2894e7a905cadfa7489 | |
| 404 | dist/2025-08-06/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=4a85be8477cf4b23971fedf3b06b404cf2231f8fe941630e3e73dc902454b96e | |
| 405 | dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=385625349ab2e79887e2630fc861dcdd039190af36748df27500f7ea45a515f9 | |
| 406 | dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=50cec6b681ae63ebcd60ce6cb6d328f49939c3cac1aa6b71ce76a5a3902cb52c | |
| 407 | dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=09a141bf2e457e91abf688c8084654e5e0b932418e351da2c0daf6cf89b77e56 | |
| 408 | dist/2025-08-06/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=7aa6d3bd020e903c842725bb3ec9dba1881f2e9cd748953c23c658ef93d49dce | |
| 409 | dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=c00a4b1ad60af59609e3bc61f042f9c4152de26687dcd120da173d61264b88ab | |
| 410 | dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=fcca5576b2f0bdab5bf7dd7ecb6ea956285aa3c129a1ea9facaf517f09f20c2d | |
| 411 | dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=434d9bff2e5693db416701730af1a71767715e98d674cf7273b32f76128ccab1 | |
| 412 | dist/2025-08-06/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=af48289fe813a45eb78373d80f01f060ebd2ce6337763d1ee8ea6f5080cb4eb1 | |
| 413 | dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=68b2704b80c8f0706dc4bdba4db3b620afecbe086a7d858749d84d56f130979b | |
| 414 | dist/2025-08-06/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=930b287659104dbf4fe759d450a4126b7a0f855fbe8fd7d3ab11aadb18ceccfa | |
| 415 | dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=7580ce2af926de7e07ad2313ae6397a624b10532556f7f9b9cee8ecd5addc697 | |
| 416 | dist/2025-08-06/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=ed19716bdb95eb04e64299c04725c7a0b92c66121856ab891bb67a797c8b1087 | |
| 417 | dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=1d4077c7b42aabe2b80a19f3c96b457901f81667d62a5be9df617543245f0d8c | |
| 418 | dist/2025-08-06/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=e0203ce7cea0c2125d8d39d92c5137b2397115c4d99f42d0b23746d0270c78d2 | |
| 419 | dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=0a836d9d2fc5824aeb4afd5eba709c0e3c6d4403ca8815356a0ac8735cbc95dc | |
| 420 | dist/2025-08-06/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=f656cb9adff0aa53f47f15a937556e9b1a9418f33dff39350e48ab8c02da987a | |
| 421 | dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=c44a884292ffeba027d3d029d6d53ccaa2bb85787e825c9cc1dca464046a7855 | |
| 422 | dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=6992586e7dc3b95ddaa630cb61f58ec88b5d7c488aed8476be25a92d0fb4a3dd | |
| 423 | dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=6e053aee8964a26385292dc2e9b671995045bb736447059e536b1e7f09c79685 | |
| 424 | dist/2025-08-06/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=611d609f23f75a2b7fe304737abaf017fcf4594d9d11cbe014e91a90ee5ab27f | |
| 425 | dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=932f888a1a604358ad40d62bc0ca9a484f47715e8a5306fe77ae610ada4671ce | |
| 426 | dist/2025-08-06/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=4eae3ed539b4ff8b39dae4ea4089081fa49807d31640129eec29b47030e8101e | |
| 427 | dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=13c65d2427c063961c19b20aa4f25bb11b3189084e2f0a798a846b95c630735b | |
| 428 | dist/2025-08-06/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=2f8e8ec9a4c0187174a0d8d3c2addf75e68a2d60920ae100f37efb5e57a45033 | |
| 429 | dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=e11b21d9aa403a1202c299390210d11d403501f6f55cc7ec24d6118461545825 | |
| 430 | dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=ece7d348df665d6ff6d061e911c6bb4c9d4f161e63e888d3a66f17b533843886 | |
| 431 | dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=d87c2370e2346587d71994ba31a0455932760507fcce680ab39322619179c429 | |
| 432 | dist/2025-08-06/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=030355ceaa2697d8b2d2de41b56cc4ef50124aa81b2f226cf0d56a1e011e0fa6 | |
| 433 | dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=d725272b6b92059afd637a3edfc6dc2b22013bf4e70a0ed1f7c5aad3c6a71fca | |
| 434 | dist/2025-08-06/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f0c3e7de4e92f696585bd6a85c30fab337548e4393c3ec5b52832f3533acb063 | |
| 435 | dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=79f6a3429c2ee29e1350bfce20f7f5ca1e5ec46720194cf3f34977fe446c79cd | |
| 436 | dist/2025-08-06/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=777568cc6df1ce1b96f291027a5024109c189e83e2e2c046a3248e3a1cbedcc6 | |
| 437 | dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=2528c1e6256bd9e73174b435802702bbe66eaaa4cff3748d3e5b7580ca7bc789 | |
| 438 | dist/2025-08-06/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=2f62d01498b57395e03ddfffc4e0b5cdf78a7fb6f5308440b8eee24637874752 | |
| 439 | dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a9b2f612748bc7a88eced4462999c67eeba0ea46f4a73977513c34c09286b0a3 | |
| 440 | dist/2025-08-06/rustfmt-nightly-x86_64-apple-darwin.tar.xz=a8137526bc41ab13a624aa5c9895abcc250f38776aeb690a7939baab1093f388 | |
| 441 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.gz=18015624ba6cc1892d944d6f3c82e0b22fc5ff85ac074d25ad80fb4af12f0172 | |
| 442 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-solaris.tar.xz=bc0f5d324b4b807b0a378aa0e132a429c57c4773c6d9d30e9215ba835de1a0a5 | |
| 443 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=de159bd0f81d54906d8020b3da80ab3319292907c3f0c9c68654f8e6ed900135 | |
| 444 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=6dd48c3a64fcc0f2f99e4cc643cf82f1a7efab1921918fd37953c64125982606 | |
| 445 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=8ba8c7ce8715fb378758ae8bd6c1538e538c2dfe86771db43b7903f18a384ad3 | |
| 446 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=4259f65663aea76e1397c677bc286588cd4b6f8694647c738efc55e5616bc084 | |
| 447 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=bfd3e1434e5b816d9d338e6c56203f58b5c1a89499ca03099d4d86b3c665f0d1 | |
| 448 | dist/2025-08-06/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=6260a7487d7d3759aea9e6691ac77ee38948a538f8b973459f444f98912753e0 | |
| 449 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=c10b36a6ac99d8e1de73c3ae0ca74ef10600baf7a3963f6885282b97f703f992 | |
| 450 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=b8de069c788f4a6c195d7a429ed656a45ea2a9a5775138de46d79c1c3591e70e | |
| 451 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b0f0d9331d213015493e080f8cd06e6ed955693981241acd692a92dd545df66f | |
| 452 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=91ed6b2792622c68a5cc3698650860373305a39162b2b643b1c219cab6debbba | |
| 453 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=b1920a45d2532f41956b2c1112cf8c590243b1417bc48f3922056e1d62a27a1d | |
| 454 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=1825ed54530deb070d6f894cc12ca157be57a37e6d7ccc6007a51674eae42082 | |
| 455 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=ac01818b1cc9130b4dcdad9db8137382655d21df9d6e7edc5cd0f84c71bbe787 | |
| 456 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=21ee5aeb048e5337b3231b4f3ca8a6bfacc3a1cc23800052093d360ca22b3b78 | |
| 457 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=020995d3e24b4e72b0166662fd2e6969f397baa728999bbd09bce76e5381e0b5 | |
| 458 | dist/2025-08-06/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=4a09cad2bd24ae6a15c83fb9098f66208219d3ab14c9fd46a3ce7a3c8efe6119 | |
| 459 | dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.gz=25e5461350634cbd4b38dce96bc6ba6a9fbdb87caed51f26dfa058105bbccb4a | |
| 460 | dist/2025-08-06/rustc-nightly-aarch64-apple-darwin.tar.xz=e8774ab1e12ba4d3d088dfb0c6a929b3fb6866db035eb10a60b203a6af59f490 | |
| 461 | dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=0094366fa4b8f33c7ec5bb75fa5116044c76f3b7bf4a96b5a48b31dbf6f080eb | |
| 462 | dist/2025-08-06/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=6686cbf9182560d9b691ac56b3e89ed76c4fe6340dd036820a1a126e2ff41689 | |
| 463 | dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=d3e23b1b5ac10b0cc406eb5397da7fff30aa4e558832379debf4410551ebdc4d | |
| 464 | dist/2025-08-06/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=fd2771191a84469c6b1fcef7e90388f4699ef087e082c9838ca2bb2d1d50b399 | |
| 465 | dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d4848e6a71e9cb6b87e46843f61da911ae81266f5c3aca10f85120d069d304bb | |
| 466 | dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=b1e9c97f2b1c06ebf1dc00cf5fa23191a86e3ef234ebaeeced2bd41b3e59b656 | |
| 467 | dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=4d68bc5ecf31127f67d1bb2359e9ca475ea7a0c396da29b00781929f1f00ba6c | |
| 468 | dist/2025-08-06/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=8588747d7ce6c5a9b68ba6805b63449695e60d2e9ea7f3f0ad5f4e5a04d9062c | |
| 469 | dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=4ebb3bd5e06737d2b61f249a674cda32a2a58e871039c37d49c2d6c8d2ecd6d9 | |
| 470 | dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=5740de96cfbdcc5261e0df10e9c7ec63e28bd553f9691a8e26e6fe9f76cbbee3 | |
| 471 | dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=a7f5f4a9b5c0b6d2cf2f86feac062018e044cfbd05c9cc8243e2ff44d8196745 | |
| 472 | dist/2025-08-06/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=a1f54aab1b4a5ebc09d9b57c892072dfd8d5280fe7a0f3dd3f643ffc72992d34 | |
| 473 | dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=cac4ed0ff044997a35471f6c291bb165b48cdcf3f0a0a4df24d7c91cbe121362 | |
| 474 | dist/2025-08-06/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=47e6083275169ef75dde6daae2bb9ca599ea03ce56d31945e9e0b42d09ebf364 | |
| 475 | dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.gz=95c87a447d33748fbfa1e9136dfb290814a7dfb1a28efc45f14f0c7830ec49bb | |
| 476 | dist/2025-08-06/rustc-nightly-i686-pc-windows-gnu.tar.xz=52929264f954609165aca5d925d6a1f0e41f78647b45edcd8a7c8c3f872c4bd7 | |
| 477 | dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.gz=f8db463c7c5aeb7fda6d0aa2e4d460d42a7fca5ec8b9b4d8a97e4f988c72a1bd | |
| 478 | dist/2025-08-06/rustc-nightly-i686-pc-windows-msvc.tar.xz=b33e23dfc673dda3eaa81d3c2d690e68cbc95bfb09864c8b2307029b0509c4f0 | |
| 479 | dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.gz=f4f243206778a3997e3ab63170182a6e210cedd47c2a17358146e3e2cb892912 | |
| 480 | dist/2025-08-06/rustc-nightly-i686-unknown-linux-gnu.tar.xz=194cda3450befacd2da23bccf836995f09a85e7e9c6d4ba5613cbb3c1768815f | |
| 481 | dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=f189ae4ab931c61eef04b5748b696070b998699315629a3b95d4f0b4cdae9ff9 | |
| 482 | dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=23c82bf0d9f5532d94a24cfaeec66fc5f02e1b28c854e5689babd41ebcfc0ad2 | |
| 483 | dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=3e76a7201dd24f9d79589445509f0c80e6902864731f71d1da3f5343a75aa5bc | |
| 484 | dist/2025-08-06/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=3a62df3e5497fee4e56bc428db422990c7df924f72dacb6897b3783560a967c8 | |
| 485 | dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=cc5c126bb1ad662dc78a3b4b039e6cd32445b45b163886180fda199cbfdae9df | |
| 486 | dist/2025-08-06/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=1c9ecfef304fb901ec6f2cfd4e170d1f02511bb2a84de664718c20c7d154e313 | |
| 487 | dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=76b6c1025d9dc045bfdfb5e0ca8e9cde674d0c40bb67f600ecb0e765b9f71f03 | |
| 488 | dist/2025-08-06/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=bf08f2bbd2197919acfcdf8db8130882ec8f77cb41371729072e7e94cc54997b | |
| 489 | dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=7e5e5816a18c3b22a5a5cd0814206c3cb53c7fa2ce3d36c9c045e1fac87b0747 | |
| 490 | dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6470b0bbe1a82064de13bd9540acbd2368421e8b000cfd8af05886a48cf11d2c | |
| 491 | dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=1a2cfbf02e55995793bdd9cf3809ace31a3d9900667ec6d5e71c6c63af26f578 | |
| 492 | dist/2025-08-06/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=7ea6594b669fa77481ff8ec4e8cf447c11e021a412584e1e60f0baed0976316e | |
| 493 | dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5cbd5821ad528d90f191a17d019b71ac2beea413b00ceec78aef9433832b2469 | |
| 494 | dist/2025-08-06/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=86002592eb275d582ec8656d903ddd2247a0fcfdb2c6d90f337735a574debb9a | |
| 495 | dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1c420af2bb6af11b2a718ff02d96794e9916a7f538d622b418f39ecd451e1fd6 | |
| 496 | dist/2025-08-06/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=1c33f80fbc3284d8499ec03bddb5bd9ebbe7e0da1aac6675d8442a3443440c3c | |
| 497 | dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.gz=366a9097aaf91fd8b2853b2f94d82b8baf162dae5ef1b514072b4da19fec87a5 | |
| 498 | dist/2025-08-06/rustc-nightly-sparcv9-sun-solaris.tar.xz=eca0aaa16e5e7006b19e56330157545d0fb56a5e590c92e041afbc8205c35ab0 | |
| 499 | dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.gz=f2665645f498cc57e0b6cb052715afd264b7bb3184be58d50f528562a1610111 | |
| 500 | dist/2025-08-06/rustc-nightly-x86_64-apple-darwin.tar.xz=2d5dba8ed862c80035ef742d9a45c1e122228219b4e1da8fd8b920eb589bbe71 | |
| 501 | dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.gz=6970602ef52246883c2df83795cca94356a1e978265facab3dd3f838707d31d3 | |
| 502 | dist/2025-08-06/rustc-nightly-x86_64-pc-solaris.tar.xz=92e7a314326015586054cdd5044c3123f41972432b2167f0dd551ee9380d66ca | |
| 503 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=5405ac07a580ba16b0f95ed0fc56a24318e8aab7abfe04c2ed3c87f9d6f1edcb | |
| 504 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=10d189c68491e15b6dd34b7f47bf8c72ccb8ab7260c4d815cb51046fd24ad76c | |
| 505 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=812a29f858412b9c256184e8e2b3d65d0c9912d7f4157a9ba640c8231caa5160 | |
| 506 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=aa22d4547d85669a17c8a475baf533614d8d0547b1e386dc11bde66f215a874c | |
| 507 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=5e60c66f60a4358c0f8b2fea5577f71f4c056c7b2d0afefd9289f782004fbc63 | |
| 508 | dist/2025-08-06/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=6d975c907e1def685c14fe6e460001af0362824f771585f9b1ccc2cc1ea71fac | |
| 509 | dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.gz=465206e95e2c6a7731ca55db9e576f1f78e9d356ba81c6687752793101c80b92 | |
| 510 | dist/2025-08-06/rustc-nightly-x86_64-unknown-freebsd.tar.xz=13cd73704262a891ea825201e6583c171f7a920c1be5372b4cccf5cbe3d294fc | |
| 511 | dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.gz=a7bf182bf19812d41e103a8d89e6c3457c1c9d0ddd800f59fdc3d94df587e3c3 | |
| 512 | dist/2025-08-06/rustc-nightly-x86_64-unknown-illumos.tar.xz=43da78e7dca1415ecd756ef13fd08a8358b8deedf406d18801f36e38843a704f | |
| 513 | dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ef6381475d22aff666429754e25855e97a4dc39e8d508c02a0e353df58afcaba | |
| 514 | dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=238910ad25562d4f7fa6c83d92f9cad5ec3817191907958fa646251c9bcdb690 | |
| 515 | dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=df2464c2f2c9233f2009ac73924e95b7dd395c8575874a3391fe2f3dfcfda327 | |
| 516 | dist/2025-08-06/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=99c5a9d7f0e7f9e3acde96bfd1d23a11100be81a3651e8267e6e0ffca6bc553d | |
| 517 | dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.gz=705dd37d72d99694234af13a561dd9995a0e4c2bfd888aa451b666f49a7083a7 | |
| 518 | dist/2025-08-06/rustc-nightly-x86_64-unknown-netbsd.tar.xz=0dc9551d63131336cd97b7bfca984970fc8e5c366b39e04a179673f7859f4c1e | |
| 399 | dist/2025-09-05/rustfmt-nightly-aarch64-apple-darwin.tar.gz=6fd7eece7221e76c2596e0472e7311fdced87e9fab26d2a4673a3242fe779bd3 | |
| 400 | dist/2025-09-05/rustfmt-nightly-aarch64-apple-darwin.tar.xz=1a662a55931f58be9ac05841360305f277f8b1e36f99bd0a2ee4d2cc92b7ad14 | |
| 401 | dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=d1c3c52cf61522697d726b32ed28d7b8b4cfadf30ec57f242e8c7f9f8e09f692 | |
| 402 | dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=2cc7cbbfa06803a2fe422ed3266f6eb519360b403c83f92259cc1b83f5ddca45 | |
| 403 | dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=61f525d050d1ff4a29cc7240912d84c9c091f25195b58411af9ef176175a3200 | |
| 404 | dist/2025-09-05/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=504b8ace2ab7ac13be143d95ed74d94940e8706ef9f53b7778da215840337e20 | |
| 405 | dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=ff48bd98d109310638822f5813042583900e2b70edd45fccd871c7c03dd1c2e6 | |
| 406 | dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=b3de2bba7858e76cdafd326f3072e4c5b534ca9b679ea62caeffb07722e9a3c9 | |
| 407 | dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=8ca4caedc50f09995dad7bc6e001cc863c524e28c45c186022ded589f3728709 | |
| 408 | dist/2025-09-05/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=8f2cfb052f9697052d89bb729d17d74583af3fa0be98f18a3c44ea518a8f4855 | |
| 409 | dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=b12ac2a38b379bf0de4a92f29ca40e1955c45273e798edd1a72bd40253de70f1 | |
| 410 | dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=87fb7185aa46f3810e09479dc8fafb66d13b41f4f40e9c4e866ea77fa47b1bb6 | |
| 411 | dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=be1e8377f3d10f4f8a07ae06ab9f649f9d2fc9cfc395abaa5f0ad10a95c4fe7a | |
| 412 | dist/2025-09-05/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=60646799fdacdafec9e0ed81357b5db70f85bb1241fe775e71b8ad3feb686116 | |
| 413 | dist/2025-09-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=ed8cade9b846efb5ac121aa70ac188fbd2e61fa9402fe68c80b2cbd3ee32ccbd | |
| 414 | dist/2025-09-05/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=0d0bfbd9cd4123e0404fe476a6f16eec6e435ce28d328dc0dd0aad257b295d64 | |
| 415 | dist/2025-09-05/rustfmt-nightly-i686-pc-windows-gnu.tar.gz=bd411db34707c36d5b60f14bba776b0b89b69d4266007a3b591c467a17ef053c | |
| 416 | dist/2025-09-05/rustfmt-nightly-i686-pc-windows-gnu.tar.xz=f0f2a6a81177ae6d06ff9b8f4a5bdf3bc8b26710aaf0f09258b32f7f710722c0 | |
| 417 | dist/2025-09-05/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=b49130da444e01fe4ef997b649aada8978b8dcca60dd38cf9e7400a7c7569e1b | |
| 418 | dist/2025-09-05/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=0195cdddc74cba2bf17eaa1d53edb1a2bc0e34cdf13c7b25a34ad9729a2635b8 | |
| 419 | dist/2025-09-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=1141897495ddca10fd6d9476a624b6a340fc2bfc619148e183bcf355a0078b18 | |
| 420 | dist/2025-09-05/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=81b31bc8b3d431120005c3c8eeff3ed194dd18e56220c175c3250855cbdcddbe | |
| 421 | dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=10a27070239e7dfcf701669c8d93ecb2d310b9fde768639a2bf5be62cd13528d | |
| 422 | dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=0ac4a529f4f62a94d5ae4cc8a4a52f0e7d57296ac0884258dcc5478e6b0b1785 | |
| 423 | dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=9d0ed6778fc4f0601be1e317438cf95c414fcab6d3207c635babb4f3a6faf2b0 | |
| 424 | dist/2025-09-05/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=e40b607faf2f37c9d654cc0b60c47ea155893a3b62236cd66728f68665becb18 | |
| 425 | dist/2025-09-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=46c029ebbfa35972b0b9e366d17c41ff8e278e01ce12634d5e3146cbf6d1a32e | |
| 426 | dist/2025-09-05/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=8d1462fd09b04a94bfb1c1841c522430b644961995bf0e19e7c8fa150628e7c7 | |
| 427 | dist/2025-09-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=5827684ccb4d38956e77858ddeadeaff2d92905c67093207bed0f38202268151 | |
| 428 | dist/2025-09-05/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=975c7d7beb5b66caed7d507aaec092fdf33de2308f4dc7de46fe74e5e15b5352 | |
| 429 | dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=8829677ab0f898c98badf22dad61094cf53c6d599b2cc76142d3d792a44f3770 | |
| 430 | dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=3d961bead4010f8a488a065ac8a4153e3c747dfcd7d5f7eeba1cad00767a7ac5 | |
| 431 | dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=0138c30ebe74e8ee838d9eef31c7882812bb52d2304f2de7c23c47dedd6a5032 | |
| 432 | dist/2025-09-05/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=bdb4b7b3c89a30c79f51b5fa33a2a29fc8313f8193bc43ee611e8ce7d80382d2 | |
| 433 | dist/2025-09-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=8e440dd400bf3eb4a144318459e111069a64bb309a5a51eeb0f0383dc48ee55f | |
| 434 | dist/2025-09-05/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=f623e1d7d38d94965d7653fdf4a272630b2b6dec81662fbbe5d2573f2f3f3b8f | |
| 435 | dist/2025-09-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=f46a8278352d5a981c6746b876fe19df3093090a866d20d24cd5cb081136b1c0 | |
| 436 | dist/2025-09-05/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=fdf8b44c6f110a33ad7f969e651ad396c880a85545aadfee8a24ca3cbed35974 | |
| 437 | dist/2025-09-05/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=59d778dea354867d64c809b40443ca0762c685dd0e5361971daab04aa7c5a5ad | |
| 438 | dist/2025-09-05/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=18628b2888d77281fc9b2ac5636ce4ec444ab0e47bbe0e8a08238f90040c20a3 | |
| 439 | dist/2025-09-05/rustfmt-nightly-x86_64-apple-darwin.tar.gz=169d9f2ee4a0c726040f4940370d1162502aa6568a0a442c92cad3fbc7bd95c2 | |
| 440 | dist/2025-09-05/rustfmt-nightly-x86_64-apple-darwin.tar.xz=7f955cfa1ab07819f31cd904b0a79c67cae70090aabc7dafffdc1f3f67463248 | |
| 441 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-solaris.tar.gz=d2cc32d6be1d0f1a8654400f0418d16e789b62db3fbc0cca0d0d492615bcf6e2 | |
| 442 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-solaris.tar.xz=3dbc29c923a6a2809a8ef561d2ad375211b09dcb107bceabbf510ab0d7b471f0 | |
| 443 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=d9b4ca2abf1062e888b31f31f517ccc6b451bd2bfdae915ec3984bc88a8be91a | |
| 444 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=00c6d92b6e82ae58e682e72c974f2dcc865820567ba44ed008e4759dfdbdca87 | |
| 445 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=e75424d0aece8d548b2c9d896291288615d08ff2a37f1c4844a70839c612e633 | |
| 446 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=cce9578d9b35bd8192a26e2dc7d7f7e7d5b9f08c7d73b3f4dde08208b448b063 | |
| 447 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=ac4282e06b0972033f974c63d2c6cbf194d4e66a1c811f443d3fa0b886868825 | |
| 448 | dist/2025-09-05/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=a2465b31855861d0e0eea072bb366480acf2bafdd7fdfdab79c809d8bbf8d8e4 | |
| 449 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=30c22a97066a5711f207c1919a1d74a328540da0d9d6f85a0cc044174049c927 | |
| 450 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=40987da0b665940f9c406cfbb4889dc101d73846730b0bdfa1382d051297ad08 | |
| 451 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=443ba10092122fbba9854abb4aa9d2e71d8e5e65b99fae6dd572909bf50f28c5 | |
| 452 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=10285942b9140efc9897965cb3a4204145e774bd1b0c2690d45d8b04498fb917 | |
| 453 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=b09af4fe367df416bce622654d9e3dfb610c564f5e6d14b200d949340595673c | |
| 454 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=1f9a585a017cee5a05190377cab105603f039fbefd9b4934278dc555dfca91b0 | |
| 455 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=24f911745fcc9f120e44acccb98f54dc6406e492915410aae17efdd00e2752c3 | |
| 456 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=48eb58ba1d58701dbff341e19fb6d446ed937cc410207b35297babafa29dd889 | |
| 457 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=c2d1cfdcd8a08bde3f9a635eaf2d6d2fbd82e4cabbbd459e3c47e64bf1581f11 | |
| 458 | dist/2025-09-05/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=ed1775b4fd3d7d1203f8749f70328ea4ade802fa0a76c4d7ab3e2d63ca1535af | |
| 459 | dist/2025-09-05/rustc-nightly-aarch64-apple-darwin.tar.gz=4b64c4148e5cdd6585a4200125cc394c6a998da3686ef758f37742ec2d33d573 | |
| 460 | dist/2025-09-05/rustc-nightly-aarch64-apple-darwin.tar.xz=fd45182f9db059bdc17f2c465dbaae22589eb8e8d2d88776437a34ddca3b7153 | |
| 461 | dist/2025-09-05/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=c14f2d7f391492d150f2f2f91af413266649cbdbdb042fc8b660b3cb141b80c7 | |
| 462 | dist/2025-09-05/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=d72ea1c571fe2376ef05cfd15fb3207ee2d27c3c851f3391dfbb082c06a5bdd0 | |
| 463 | dist/2025-09-05/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=3a485d8fd8d58fdfbc1216e51414aa4d90f0c7285a99abea0fa5935d2337251b | |
| 464 | dist/2025-09-05/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=7317060a29eecd2e28d47f0ff8780150059756b07e2bc9137c3877be8af593b7 | |
| 465 | dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=58a53ae147de1beb0a53629898bf7c51097351271be3713a2e2344b86a4080a4 | |
| 466 | dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=f79d2730843dbea9e9588fd1c1b0d854441969d8f93f76021f06af2efe22b845 | |
| 467 | dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=eddf23e28b8067021e80883faf2eb1d6d3005a6e8419a1232b84236bea286f78 | |
| 468 | dist/2025-09-05/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=4f0af1a66050f5e2d9d48b696349b9ccd420bdcfdb88b251a6655cc22a11949b | |
| 469 | dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=fd2f0446e3c993d746e8a5f72ccebd8b0a49172316ac1d1c58bad10596becbf3 | |
| 470 | dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=0b06e7ba47621819b4e59e048e5d336b3d6978e906c7363f06bbc804e49f1046 | |
| 471 | dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=97d7c34b53628f28e6636fae738a18d0f1f4c60a9febddfb7145e6b91fcf3fdc | |
| 472 | dist/2025-09-05/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=323025215bf851024a7eb6566ad7dc5719832d81e8d46e70adaece98adc5644b | |
| 473 | dist/2025-09-05/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=3017e03222d030448ffe2805624143540197bd6d3b3e93f9f73469ace25ae4be | |
| 474 | dist/2025-09-05/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=4f6e86b185fb54f7a0b7d09a0faae7daac722351354f6abebd388efb3037dfa0 | |
| 475 | dist/2025-09-05/rustc-nightly-i686-pc-windows-gnu.tar.gz=292c3770b96cde97072d70c58234488f955ed5582b7c3044c6de66891e73d639 | |
| 476 | dist/2025-09-05/rustc-nightly-i686-pc-windows-gnu.tar.xz=6855d3fd9040fb4da554fd732eaf8a1c723921c35bb8a8efb31c78af69b2e4ec | |
| 477 | dist/2025-09-05/rustc-nightly-i686-pc-windows-msvc.tar.gz=64a86a2971ed9934bbb6aaa0afc2a7f747da463afb55b51a7c5fdbdaa294e437 | |
| 478 | dist/2025-09-05/rustc-nightly-i686-pc-windows-msvc.tar.xz=c98f1fc3e077b8c8eb3e526c416a6551c08c62e58be57b4a4c7d59670bc435f9 | |
| 479 | dist/2025-09-05/rustc-nightly-i686-unknown-linux-gnu.tar.gz=5481c97d788899f896473380dde0877808489bc4a0ed6d98265558631fa67a57 | |
| 480 | dist/2025-09-05/rustc-nightly-i686-unknown-linux-gnu.tar.xz=afadaae945c0b9a8b50dbdee28791e0c03c880cb22d3c20996eeb7fab94df0bf | |
| 481 | dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=18b276a2464b6c5a817d72384f25442c7619cac05b2d8d0af212c0dad96ccfc6 | |
| 482 | dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=b74323cd2dbee966eebe8e63e24fae026ecd900a025e9167cca0341e50333cc3 | |
| 483 | dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=916dc5144107d9173479b320b55b0a95d2d42156c69fbdb0f21377d825fe0892 | |
| 484 | dist/2025-09-05/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=3a83da72aa4a6553ecd957af35a05274528dc79f87d24d8470c20b8b4478b05b | |
| 485 | dist/2025-09-05/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=59e031b6b79a1f11406c0640e1a357f2941967ea8c034a94148d60928038e58e | |
| 486 | dist/2025-09-05/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=53f0e33cf2651d5dc8931ec5af8f04994188d8f9a10a5c61bd72cc822df34501 | |
| 487 | dist/2025-09-05/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=0eec56e3b725d918cb21e494a803b2e38eb6d744f64f1a82481a4c704eb7c1f0 | |
| 488 | dist/2025-09-05/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=5efc97abb235f349c6cc952b4a1e4dae7d56d70b0f8b8da2a1060b85f9b734fd | |
| 489 | dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=cb45bbcdf8841b1ac184a0aacc909f153c830e8051260e09ca4e32c1f048e2fb | |
| 490 | dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=1c9ddddb90d45612e4fd190fb71e527b523df13146343dde200580fb2b638794 | |
| 491 | dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=3a9bdd4d14e8f121d3051944ee83a901b5ca4c0921f2d01e34596fb7450b49e3 | |
| 492 | dist/2025-09-05/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=732b9abb8a80191884fe1ff1d4d923cc1b74c21b81e6327bc5979ae526337400 | |
| 493 | dist/2025-09-05/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=1826e74200fe286478e1659ab88ea86b43efa7b023074d00dbc814d80bebc883 | |
| 494 | dist/2025-09-05/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=c30b52d0f474fd6193bb1b3e147fb79fa8cc31e5db38444f023d84d1c2d93d12 | |
| 495 | dist/2025-09-05/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=c330067621ed25d8383f27e494346eca4d7d4866e48f331f2ec897ff1c386e56 | |
| 496 | dist/2025-09-05/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=cb4097ea582a83a94cab80ff2f36b6f7141c140d75c30b1d261a1ddd4ea45bd4 | |
| 497 | dist/2025-09-05/rustc-nightly-sparcv9-sun-solaris.tar.gz=0af19e764f10333017a3ab66020b82c7185ad648d1230b68f10977e0affb937f | |
| 498 | dist/2025-09-05/rustc-nightly-sparcv9-sun-solaris.tar.xz=a22cfb55cdd122dd99bf3566eabd781bb2ecded90c71a41fd33b1e0588bcc39c | |
| 499 | dist/2025-09-05/rustc-nightly-x86_64-apple-darwin.tar.gz=163a07b91e36e85c6c41368598793667414cdc6cadc980866811234539f3aec3 | |
| 500 | dist/2025-09-05/rustc-nightly-x86_64-apple-darwin.tar.xz=76711800685b39b3b75945395682062c40efe3195f9979784bf318837e21768a | |
| 501 | dist/2025-09-05/rustc-nightly-x86_64-pc-solaris.tar.gz=69142a6c04703c3c8309c6fdf66b25831bf9efa3ee70cc93da4b5b75f901b29a | |
| 502 | dist/2025-09-05/rustc-nightly-x86_64-pc-solaris.tar.xz=7e535f4aa136284e4bdfd4d56891caac6844dab91e1b711fa3914a5974dfcb60 | |
| 503 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ff0ea563126ff28df297258001d9fac4dbd85788b5d27a0f5d6be75306f21139 | |
| 504 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=6b66adcaa9a5332979591464242423897f59276e9e2cbeb9ab038a72e72c3a5c | |
| 505 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=64cac5e377bc115a8f8176719575903e695337941db43cfb35546d65c0723130 | |
| 506 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=11e2765e4b3e2296ea05ecf735cf7b5f7beb08d76d12449cfae67f88bab02819 | |
| 507 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=c7d15ae7cd5af774ae70e63fec3ba8723b85fa4c4640917b3960907eedb30b39 | |
| 508 | dist/2025-09-05/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=55036567af270cdac046fb4306e515787ca6ef5073617311fac79fb87ffe9366 | |
| 509 | dist/2025-09-05/rustc-nightly-x86_64-unknown-freebsd.tar.gz=2d24470d2bb4c4d2605c15f1b2654cc45805384babb73b1960e8aea0b8cc227d | |
| 510 | dist/2025-09-05/rustc-nightly-x86_64-unknown-freebsd.tar.xz=fa41782cb2e22aba30d1619db1f478c0305944ceb4de1d1001f221c5c68c104e | |
| 511 | dist/2025-09-05/rustc-nightly-x86_64-unknown-illumos.tar.gz=d0f9785f76c59f3a67a499cfff4a5639f3ae05cbc76750b867faaa60b7d67f78 | |
| 512 | dist/2025-09-05/rustc-nightly-x86_64-unknown-illumos.tar.xz=925e473c6e31d8811879a805358cfd2e5ab8f4de836c270d02dc8403771bed3a | |
| 513 | dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ebac845114b89dfe7d0efc0cfe8820902faad617ed21eb2a701d73cf7b544a85 | |
| 514 | dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=2512a5462e3f46c95ed4aba4228282a357b3e0694e9db117a857196448fe7bcc | |
| 515 | dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=b4a5d364b84464e9a92140fff50349d4942b8d970b64150a4bc6d720cc6c4a4e | |
| 516 | dist/2025-09-05/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=6c57c2edc305737530f8551d789ee79ff952f42a0d52d6f8d7d7f1ea2027cfca | |
| 517 | dist/2025-09-05/rustc-nightly-x86_64-unknown-netbsd.tar.gz=f3192ded327875d5a27fb50c690e3fce36669e8f71c47de304dc21edad573ff9 | |
| 518 | dist/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( |
| 303 | 303 | } |
| 304 | 304 | |
| 305 | 305 | if js_lint { |
| 306 | rustdoc_js::lint(outdir, librustdoc_path, tools_path)?; | |
| 306 | rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless)?; | |
| 307 | 307 | rustdoc_js::es_check(outdir, librustdoc_path)?; |
| 308 | 308 | } |
| 309 | 309 |
src/tools/tidy/src/extra_checks/rustdoc_js.rs+21-9| ... | ... | @@ -40,13 +40,18 @@ fn rustdoc_js_files(librustdoc_path: &Path) -> Vec<PathBuf> { |
| 40 | 40 | return files; |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | fn 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 | )?; | |
| 43 | fn 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)?; | |
| 50 | 55 | match child.wait() { |
| 51 | 56 | Ok(exit_status) => { |
| 52 | 57 | if exit_status.success() { |
| ... | ... | @@ -62,16 +67,23 @@ pub(super) fn lint( |
| 62 | 67 | outdir: &Path, |
| 63 | 68 | librustdoc_path: &Path, |
| 64 | 69 | tools_path: &Path, |
| 70 | bless: bool, | |
| 65 | 71 | ) -> Result<(), super::Error> { |
| 66 | 72 | let files_to_check = rustdoc_js_files(librustdoc_path); |
| 67 | 73 | 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)?; | |
| 69 | 75 | |
| 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 | )?; | |
| 71 | 82 | run_eslint( |
| 72 | 83 | outdir, |
| 73 | 84 | &[tools_path.join("rustdoc-gui/tester.js")], |
| 74 | 85 | tools_path.join("rustdoc-gui"), |
| 86 | bless, | |
| 75 | 87 | )?; |
| 76 | 88 | Ok(()) |
| 77 | 89 | } |
src/tools/unicode-table-generator/src/main.rs+1-1| ... | ... | @@ -228,7 +228,7 @@ fn main() { |
| 228 | 228 | |
| 229 | 229 | let mut table_file = String::new(); |
| 230 | 230 | 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", | |
| 232 | 232 | ); |
| 233 | 233 | |
| 234 | 234 | let mut total_bytes = 0; |
tests/run-make/apple-c-available-links/foo.c created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | int 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 @@ |
| 1 | unsafe extern "C" { | |
| 2 | safe fn foo() -> core::ffi::c_int; | |
| 3 | } | |
| 4 | ||
| 5 | fn 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 | ||
| 6 | use run_make_support::{cc, rustc, target}; | |
| 7 | ||
| 8 | fn 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" |
| 4 | 4 | assert-attribute: (".scraped-example-title a", {"href": "../src/bar/bar.rs.html#2"}) |
| 5 | 5 | click: ".scraped-example-title a" |
| 6 | 6 | wait-for-property: ("h1", {"innerText": "bar/\nbar.rs"}) |
| 7 | // Ensure that the `--html-after-content` option was correctly handled. | |
| 8 | assert: "#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 @@ |
| 1 | 1 | //@ run-flags:-Zrustdoc-scrape-examples |
| 2 | //@ compile-flags: --html-after-content empty.html | |
| 2 | //@ compile-flags: --html-after-content extra.html | |
| 3 | 3 | pub struct ObscurelyNamedType1; |
| 4 | 4 | |
| 5 | 5 | impl ObscurelyNamedType1 { |
triagebot.toml+1| ... | ... | @@ -380,6 +380,7 @@ trigger_files = [ |
| 380 | 380 | [autolabel."O-apple"] |
| 381 | 381 | trigger_files = [ |
| 382 | 382 | "library/std/src/os/darwin", |
| 383 | "library/std/src/sys/platform_version/darwin", | |
| 383 | 384 | "library/std/src/sys/sync/thread_parking/darwin.rs", |
| 384 | 385 | "compiler/rustc_target/src/spec/base/apple", |
| 385 | 386 | ] |