Skip to content

Rollup of 10 pull requests #139746

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Apr 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0acac2c
std: Fix build for NuttX targets
thaliaarchi Mar 26, 2025
15e1a66
Use -C target-cpu=z13 on s390x vector test
fneddy Mar 31, 2025
44d1d86
libtest: Pass the test's panic payload as Option instead of Result
Zalathar Apr 8, 2025
7711688
update miniz_oxide to 0.8.8
oyvindln Apr 9, 2025
0ca3127
compiletest: Make `SUGGESTION` annotations viral
petrochenkov Apr 10, 2025
909b6c9
compiletest: Turn `TestProps::require_annotations` into a set
petrochenkov Apr 10, 2025
ad72ba2
dev-guide: Document `dont-require-annotations`
petrochenkov Apr 10, 2025
06dd9e2
compiletest: Trim the value of `dont-require-annotations`
petrochenkov Apr 10, 2025
dc0fbca
Fix profiler_builtins build script to handle full path to profiler lib
Apr 11, 2025
b613e97
Use with_native_path for Windows
ChrisDenton Apr 11, 2025
6ffebb6
Move args into std::sys
thaliaarchi Apr 12, 2025
e014fd6
Use unsupported args for espidf and vita
thaliaarchi Apr 12, 2025
bea2022
Unify owned Args types between platforms
thaliaarchi Apr 12, 2025
6ba9649
End all lines in src/stage0 with trailing newline
dtolnay Apr 12, 2025
5d90ccb
Move `select_unpredictable` to the `hint` module
Amanieu Apr 12, 2025
9d2d6a0
Rollup merge of #138972 - thaliaarchi:nuttx-build, r=Mark-Simulacrum
ChrisDenton Apr 13, 2025
f1b31ae
Rollup merge of #139177 - fneddy:fix_s390x_codegen_bswap, r=Mark-Simu…
ChrisDenton Apr 13, 2025
bde65bd
Rollup merge of #139511 - Zalathar:panic-payload, r=Mark-Simulacrum
ChrisDenton Apr 13, 2025
cc9420f
Rollup merge of #139605 - oyvindln:update_miniz_oxide_0_8, r=Mark-Sim…
ChrisDenton Apr 13, 2025
423e7b8
Rollup merge of #139618 - petrochenkov:virsugg, r=jieyouxu
ChrisDenton Apr 13, 2025
f2a2135
Rollup merge of #139677 - jchecahi:profiler-builtin-rtlib-path-fix, r…
ChrisDenton Apr 13, 2025
8a6d6f5
Rollup merge of #139683 - ChrisDenton:windows-with-native, r=tgross35…
ChrisDenton Apr 13, 2025
daed9e2
Rollup merge of #139710 - thaliaarchi:move-args-pal, r=joboet
ChrisDenton Apr 13, 2025
54aff1f
Rollup merge of #139721 - dtolnay:stage0newline, r=onur-ozkan
ChrisDenton Apr 13, 2025
f1d0b9c
Rollup merge of #139726 - Amanieu:select_unpredictable_hint, r=dtolnay
ChrisDenton Apr 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1212,7 +1212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
dependencies = [
"crc32fast",
"miniz_oxide 0.8.7",
"miniz_oxide 0.8.8",
]

[[package]]
Expand Down Expand Up @@ -2282,9 +2282,9 @@ dependencies = [

[[package]]
name = "miniz_oxide"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
]
Expand Down
4 changes: 2 additions & 2 deletions library/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ dependencies = [

[[package]]
name = "miniz_oxide"
version = "0.8.7"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
dependencies = [
"adler2",
"compiler_builtins",
Expand Down
48 changes: 0 additions & 48 deletions library/core/src/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,52 +61,4 @@ impl bool {
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }
}

/// Returns either `true_val` or `false_val` depending on the value of
/// `self`, with a hint to the compiler that `self` is unlikely
/// to be correctly predicted by a CPU’s branch predictor.
///
/// This method is functionally equivalent to
/// ```ignore (this is just for illustrative purposes)
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
/// if b { true_val } else { false_val }
/// }
/// ```
/// but might generate different assembly. In particular, on platforms with
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
/// on ARM) the optimizer might use these instructions to avoid branches,
/// which can benefit performance if the branch predictor is struggling
/// with predicting `condition`, such as in an implementation of binary
/// search.
///
/// Note however that this lowering is not guaranteed (on any platform) and
/// should not be relied upon when trying to write constant-time code. Also
/// be aware that this lowering might *decrease* performance if `condition`
/// is well-predictable. It is advisable to perform benchmarks to tell if
/// this function is useful.
///
/// # Examples
///
/// Distribute values evenly between two buckets:
/// ```
/// #![feature(select_unpredictable)]
///
/// use std::hash::BuildHasher;
///
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
/// let hash = hasher.hash_one(&v);
/// let bucket = (hash % 2 == 0).select_unpredictable(bucket_one, bucket_two);
/// bucket.push(v);
/// }
/// # let hasher = std::collections::hash_map::RandomState::new();
/// # let mut bucket_one = Vec::new();
/// # let mut bucket_two = Vec::new();
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
/// ```
#[inline(always)]
#[unstable(feature = "select_unpredictable", issue = "133962")]
pub fn select_unpredictable<T>(self, true_val: T, false_val: T) -> T {
crate::intrinsics::select_unpredictable(self, true_val, false_val)
}
}
49 changes: 49 additions & 0 deletions library/core/src/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,52 @@ pub const fn unlikely(b: bool) -> bool {
pub const fn cold_path() {
crate::intrinsics::cold_path()
}

/// Returns either `true_val` or `false_val` depending on the value of `b`,
/// with a hint to the compiler that `b` is unlikely to be correctly
/// predicted by a CPU’s branch predictor.
///
/// This method is functionally equivalent to
/// ```ignore (this is just for illustrative purposes)
/// fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
/// if b { true_val } else { false_val }
/// }
/// ```
/// but might generate different assembly. In particular, on platforms with
/// a conditional move or select instruction (like `cmov` on x86 or `csel`
/// on ARM) the optimizer might use these instructions to avoid branches,
/// which can benefit performance if the branch predictor is struggling
/// with predicting `condition`, such as in an implementation of binary
/// search.
///
/// Note however that this lowering is not guaranteed (on any platform) and
/// should not be relied upon when trying to write constant-time code. Also
/// be aware that this lowering might *decrease* performance if `condition`
/// is well-predictable. It is advisable to perform benchmarks to tell if
/// this function is useful.
///
/// # Examples
///
/// Distribute values evenly between two buckets:
/// ```
/// #![feature(select_unpredictable)]
///
/// use std::hash::BuildHasher;
/// use std::hint;
///
/// fn append<H: BuildHasher>(hasher: &H, v: i32, bucket_one: &mut Vec<i32>, bucket_two: &mut Vec<i32>) {
/// let hash = hasher.hash_one(&v);
/// let bucket = hint::select_unpredictable(hash % 2 == 0, bucket_one, bucket_two);
/// bucket.push(v);
/// }
/// # let hasher = std::collections::hash_map::RandomState::new();
/// # let mut bucket_one = Vec::new();
/// # let mut bucket_two = Vec::new();
/// # append(&hasher, 42, &mut bucket_one, &mut bucket_two);
/// # assert_eq!(bucket_one.len() + bucket_two.len(), 1);
/// ```
#[inline(always)]
#[unstable(feature = "select_unpredictable", issue = "133962")]
pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
crate::intrinsics::select_unpredictable(b, true_val, false_val)
}
2 changes: 1 addition & 1 deletion library/core/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1326,7 +1326,7 @@ pub const fn unlikely(b: bool) -> bool {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The public form of this instrinsic is [`bool::select_unpredictable`].
/// The public form of this instrinsic is [`core::hint::select_unpredictable`].
#[unstable(feature = "core_intrinsics", issue = "none")]
#[rustc_intrinsic]
#[rustc_nounwind]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2822,7 +2822,7 @@ impl<T> [T] {
// Binary search interacts poorly with branch prediction, so force
// the compiler to use conditional moves if supported by the target
// architecture.
base = (cmp == Greater).select_unpredictable(base, mid);
base = hint::select_unpredictable(cmp == Greater, base, mid);

// This is imprecise in the case where `size` is odd and the
// comparison returns Greater: the mid element still gets included
Expand Down
18 changes: 9 additions & 9 deletions library/core/src/slice/sort/shared/smallsort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::mem::{self, ManuallyDrop, MaybeUninit};
use crate::slice::sort::shared::FreezeMarker;
use crate::{intrinsics, ptr, slice};
use crate::{hint, intrinsics, ptr, slice};

// It's important to differentiate between SMALL_SORT_THRESHOLD performance for
// small slices and small-sort performance sorting small sub-slices as part of
Expand Down Expand Up @@ -408,8 +408,8 @@ where
// }

// The goal is to generate cmov instructions here.
let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
let v_a_swap = hint::select_unpredictable(should_swap, v_b, v_a);
let v_b_swap = hint::select_unpredictable(should_swap, v_a, v_b);

let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
ptr::copy(v_a_swap, v_a, 1);
Expand Down Expand Up @@ -640,15 +640,15 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
// 1, 1 | c b a d
let c3 = is_less(&*c, &*a);
let c4 = is_less(&*d, &*b);
let min = c3.select_unpredictable(c, a);
let max = c4.select_unpredictable(b, d);
let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
let min = hint::select_unpredictable(c3, c, a);
let max = hint::select_unpredictable(c4, b, d);
let unknown_left = hint::select_unpredictable(c3, a, hint::select_unpredictable(c4, c, b));
let unknown_right = hint::select_unpredictable(c4, d, hint::select_unpredictable(c3, b, c));

// Sort the last two unknown elements.
let c5 = is_less(&*unknown_right, &*unknown_left);
let lo = c5.select_unpredictable(unknown_right, unknown_left);
let hi = c5.select_unpredictable(unknown_left, unknown_right);
let lo = hint::select_unpredictable(c5, unknown_right, unknown_left);
let hi = hint::select_unpredictable(c5, unknown_left, unknown_right);

ptr::copy_nonoverlapping(min, dst, 1);
ptr::copy_nonoverlapping(lo, dst.add(1), 1);
Expand Down
10 changes: 8 additions & 2 deletions library/profiler_builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ use std::path::PathBuf;

fn main() {
if let Ok(rt) = tracked_env_var("LLVM_PROFILER_RT_LIB") {
println!("cargo::rustc-link-lib=static:+verbatim={rt}");
return;
let rt = PathBuf::from(rt);
if let Some(lib) = rt.file_name() {
if let Some(dir) = rt.parent() {
println!("cargo::rustc-link-search=native={}", dir.display());
}
println!("cargo::rustc-link-lib=static:+verbatim={}", lib.to_str().unwrap());
return;
}
}

let target_os = env::var("CARGO_CFG_TARGET_OS").expect("CARGO_CFG_TARGET_OS was not set");
Expand Down
43 changes: 43 additions & 0 deletions library/std/src/sys/args/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use crate::ffi::OsString;
use crate::{fmt, vec};

pub struct Args {
iter: vec::IntoIter<OsString>,
}

impl !Send for Args {}
impl !Sync for Args {}

impl Args {
pub(super) fn new(args: Vec<OsString>) -> Self {
Args { iter: args.into_iter() }
}
}

impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}

impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}

impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use crate::ffi::{CStr, OsString, c_char};
use crate::os::hermit::ffi::OsStringExt;
use crate::ptr;
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::atomic::{AtomicIsize, AtomicPtr};
use crate::{fmt, ptr, vec};

#[path = "common.rs"]
mod common;
pub use common::Args;

static ARGC: AtomicIsize = AtomicIsize::new(0);
static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
Expand All @@ -27,40 +31,5 @@ pub fn args() -> Args {
})
.collect();

Args { iter: args.into_iter() }
}

pub struct Args {
iter: vec::IntoIter<OsString>,
}

impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iter.as_slice().fmt(f)
}
}

impl !Send for Args {}
impl !Sync for Args {}

impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}

impl ExactSizeIterator for Args {
fn len(&self) -> usize {
self.iter.len()
}
}

impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
self.iter.next_back()
}
Args::new(args)
}
34 changes: 34 additions & 0 deletions library/std/src/sys/args/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! Platform-dependent command line arguments abstraction.

#![forbid(unsafe_op_in_unsafe_fn)]

cfg_if::cfg_if! {
if #[cfg(all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))))] {
mod unix;
pub use unix::*;
} else if #[cfg(target_family = "windows")] {
mod windows;
pub use windows::*;
} else if #[cfg(target_os = "hermit")] {
mod hermit;
pub use hermit::*;
} else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
mod sgx;
pub use sgx::*;
} else if #[cfg(target_os = "uefi")] {
mod uefi;
pub use uefi::*;
} else if #[cfg(target_os = "wasi")] {
mod wasi;
pub use wasi::*;
} else if #[cfg(target_os = "xous")] {
mod xous;
pub use xous::*;
} else if #[cfg(target_os = "zkvm")] {
mod zkvm;
pub use zkvm::*;
} else {
mod unsupported;
pub use unsupported::*;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use super::abi::usercalls::alloc;
use super::abi::usercalls::raw::ByteBuffer;
#![allow(fuzzy_provenance_casts)] // FIXME: this module systematically confuses pointers and integers

use crate::ffi::OsString;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os_str::Buf;
use crate::sys::pal::abi::usercalls::alloc;
use crate::sys::pal::abi::usercalls::raw::ByteBuffer;
use crate::sys_common::FromInner;
use crate::{fmt, slice};

Expand Down
Loading
Loading