Skip to content

Commit 032af18

Browse files
committed
Auto merge of #125902 - workingjubilee:rollup-f8x6iif, r=workingjubilee
Rollup of 6 pull requests Successful merges: - #121062 (Change f32::midpoint to upcast to f64) - #125808 (Migrate `run-make/c-link-to-rust-dylib` to `rmake.rs`) - #125884 (Implement feature `integer_sign_cast`) - #125890 (Improve compiletest expected/not found formatting) - #125896 (compiletest: fix outdated rmake.rs comment) - #125898 (typo: depending from -> on) r? `@ghost` `@rustbot` modify labels: rollup
2 parents a6416d8 + 72ea7e9 commit 032af18

File tree

13 files changed

+218
-69
lines changed

13 files changed

+218
-69
lines changed

library/core/src/num/f32.rs

+36-19
Original file line numberDiff line numberDiff line change
@@ -1030,25 +1030,42 @@ impl f32 {
10301030
/// ```
10311031
#[unstable(feature = "num_midpoint", issue = "110840")]
10321032
pub fn midpoint(self, other: f32) -> f32 {
1033-
const LO: f32 = f32::MIN_POSITIVE * 2.;
1034-
const HI: f32 = f32::MAX / 2.;
1035-
1036-
let (a, b) = (self, other);
1037-
let abs_a = a.abs_private();
1038-
let abs_b = b.abs_private();
1039-
1040-
if abs_a <= HI && abs_b <= HI {
1041-
// Overflow is impossible
1042-
(a + b) / 2.
1043-
} else if abs_a < LO {
1044-
// Not safe to halve a
1045-
a + (b / 2.)
1046-
} else if abs_b < LO {
1047-
// Not safe to halve b
1048-
(a / 2.) + b
1049-
} else {
1050-
// Not safe to halve a and b
1051-
(a / 2.) + (b / 2.)
1033+
cfg_if! {
1034+
if #[cfg(any(
1035+
target_arch = "x86_64",
1036+
target_arch = "aarch64",
1037+
all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"),
1038+
all(target_arch = "arm", target_feature="vfp2"),
1039+
target_arch = "wasm32",
1040+
target_arch = "wasm64",
1041+
))] {
1042+
// whitelist the faster implementation to targets that have known good 64-bit float
1043+
// implementations. Falling back to the branchy code on targets that don't have
1044+
// 64-bit hardware floats or buggy implementations.
1045+
// see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114
1046+
((f64::from(self) + f64::from(other)) / 2.0) as f32
1047+
} else {
1048+
const LO: f32 = f32::MIN_POSITIVE * 2.;
1049+
const HI: f32 = f32::MAX / 2.;
1050+
1051+
let (a, b) = (self, other);
1052+
let abs_a = a.abs_private();
1053+
let abs_b = b.abs_private();
1054+
1055+
if abs_a <= HI && abs_b <= HI {
1056+
// Overflow is impossible
1057+
(a + b) / 2.
1058+
} else if abs_a < LO {
1059+
// Not safe to halve a
1060+
a + (b / 2.)
1061+
} else if abs_b < LO {
1062+
// Not safe to halve b
1063+
(a / 2.) + b
1064+
} else {
1065+
// Not safe to halve a and b
1066+
(a / 2.) + (b / 2.)
1067+
}
1068+
}
10521069
}
10531070
}
10541071

library/core/src/num/int_macros.rs

+24
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,30 @@ macro_rules! int_impl {
183183
(self as $UnsignedT).trailing_ones()
184184
}
185185

186+
/// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size.
187+
///
188+
/// This produces the same result as an `as` cast, but ensures that the bit-width remains
189+
/// the same.
190+
///
191+
/// # Examples
192+
///
193+
/// Basic usage:
194+
///
195+
/// ```
196+
/// #![feature(integer_sign_cast)]
197+
///
198+
#[doc = concat!("let n = -1", stringify!($SelfT), ";")]
199+
///
200+
#[doc = concat!("assert_eq!(n.cast_unsigned(), ", stringify!($UnsignedT), "::MAX);")]
201+
/// ```
202+
#[unstable(feature = "integer_sign_cast", issue = "125882")]
203+
#[must_use = "this returns the result of the operation, \
204+
without modifying the original"]
205+
#[inline(always)]
206+
pub const fn cast_unsigned(self) -> $UnsignedT {
207+
self as $UnsignedT
208+
}
209+
186210
/// Shifts the bits to the left by a specified amount, `n`,
187211
/// wrapping the truncated bits to the end of the resulting integer.
188212
///

library/core/src/num/uint_macros.rs

+24
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,30 @@ macro_rules! uint_impl {
184184
(!self).trailing_zeros()
185185
}
186186

187+
/// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size.
188+
///
189+
/// This produces the same result as an `as` cast, but ensures that the bit-width remains
190+
/// the same.
191+
///
192+
/// # Examples
193+
///
194+
/// Basic usage:
195+
///
196+
/// ```
197+
/// #![feature(integer_sign_cast)]
198+
///
199+
#[doc = concat!("let n = ", stringify!($SelfT), "::MAX;")]
200+
///
201+
#[doc = concat!("assert_eq!(n.cast_signed(), -1", stringify!($SignedT), ");")]
202+
/// ```
203+
#[unstable(feature = "integer_sign_cast", issue = "125882")]
204+
#[must_use = "this returns the result of the operation, \
205+
without modifying the original"]
206+
#[inline(always)]
207+
pub const fn cast_signed(self) -> $SignedT {
208+
self as $SignedT
209+
}
210+
187211
/// Shifts the bits to the left by a specified amount, `n`,
188212
/// wrapping the truncated bits to the end of the resulting integer.
189213
///

library/core/src/str/pattern.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
342342
///
343343
/// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
344344
/// the pattern `"aa"` in the haystack `"aaa"` matches as either
345-
/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched.
345+
/// `"[aa]a"` or `"a[aa]"`, depending on which side it is searched.
346346
pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
347347

348348
/////////////////////////////////////////////////////////////////////////////

library/core/tests/num/mod.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ assume_usize_width! {
729729
}
730730

731731
macro_rules! test_float {
732-
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
732+
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
733733
mod $modname {
734734
#[test]
735735
fn min() {
@@ -880,6 +880,27 @@ macro_rules! test_float {
880880
assert!(($nan as $fty).midpoint(1.0).is_nan());
881881
assert!((1.0 as $fty).midpoint($nan).is_nan());
882882
assert!(($nan as $fty).midpoint($nan).is_nan());
883+
884+
// test if large differences in magnitude are still correctly computed.
885+
// NOTE: that because of how small x and y are, x + y can never overflow
886+
// so (x + y) / 2.0 is always correct
887+
// in particular, `2.pow(i)` will never be at the max exponent, so it could
888+
// be safely doubled, while j is significantly smaller.
889+
for i in $max_exp.saturating_sub(64)..$max_exp {
890+
for j in 0..64u8 {
891+
let large = <$fty>::from(2.0f32).powi(i);
892+
// a much smaller number, such that there is no chance of overflow to test
893+
// potential double rounding in midpoint's implementation.
894+
let small = <$fty>::from(2.0f32).powi($max_exp - 1)
895+
* <$fty>::EPSILON
896+
* <$fty>::from(j);
897+
898+
let naive = (large + small) / 2.0;
899+
let midpoint = large.midpoint(small);
900+
901+
assert_eq!(naive, midpoint);
902+
}
903+
}
883904
}
884905
#[test]
885906
fn rem_euclid() {
@@ -912,7 +933,8 @@ test_float!(
912933
f32::NAN,
913934
f32::MIN,
914935
f32::MAX,
915-
f32::MIN_POSITIVE
936+
f32::MIN_POSITIVE,
937+
f32::MAX_EXP
916938
);
917939
test_float!(
918940
f64,
@@ -922,5 +944,6 @@ test_float!(
922944
f64::NAN,
923945
f64::MIN,
924946
f64::MAX,
925-
f64::MIN_POSITIVE
947+
f64::MIN_POSITIVE,
948+
f64::MAX_EXP
926949
);

library/std/src/sys/thread_local/fast_local/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Thread local support for platforms with native TLS.
22
//!
33
//! To achieve the best performance, we choose from four different types for
4-
//! the TLS variable, depending from the method of initialization used (`const`
4+
//! the TLS variable, depending on the method of initialization used (`const`
55
//! or lazy) and the drop requirements of the stored type:
66
//!
77
//! | | `Drop` | `!Drop` |

src/tools/compiletest/src/errors.rs

+12
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ pub struct Error {
5757
pub msg: String,
5858
}
5959

60+
impl Error {
61+
pub fn render_for_expected(&self) -> String {
62+
use colored::Colorize;
63+
format!(
64+
"{: <10}line {: >3}: {}",
65+
self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
66+
self.line_num,
67+
self.msg.cyan(),
68+
)
69+
}
70+
}
71+
6072
#[derive(PartialEq, Debug)]
6173
enum WhichLine {
6274
ThisLine,

src/tools/compiletest/src/main.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
use std::{env, sync::Arc};
1+
use std::{env, io::IsTerminal, sync::Arc};
22

33
use compiletest::{common::Mode, log_config, parse_config, run_tests};
44

55
fn main() {
66
tracing_subscriber::fmt::init();
77

8+
// colored checks stdout by default, but for some reason only stderr is a terminal.
9+
// compiletest *does* print many things to stdout, but it doesn't really matter.
10+
if std::io::stderr().is_terminal()
11+
&& matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
12+
{
13+
colored::control::set_override(true);
14+
}
15+
816
let config = Arc::new(parse_config(env::args().collect()));
917

1018
if config.valgrind_path.is_none() && config.force_valgrind {

src/tools/compiletest/src/runtest.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ use crate::json;
1717
use crate::read2::{read2_abbreviated, Truncated};
1818
use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt};
1919
use crate::ColorConfig;
20+
use colored::Colorize;
2021
use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
2122
use regex::{Captures, Regex};
2223
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
23-
2424
use std::collections::{HashMap, HashSet};
2525
use std::env;
2626
use std::ffi::{OsStr, OsString};
@@ -1493,14 +1493,22 @@ impl<'test> TestCx<'test> {
14931493
unexpected.len(),
14941494
not_found.len()
14951495
));
1496-
println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline);
1496+
println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
14971497
if !unexpected.is_empty() {
1498-
println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
1498+
println!("{}", "--- unexpected errors (from JSON output) ---".green());
1499+
for error in &unexpected {
1500+
println!("{}", error.render_for_expected());
1501+
}
1502+
println!("{}", "---".green());
14991503
}
15001504
if !not_found.is_empty() {
1501-
println!("not found errors (from test file): {:#?}\n", not_found);
1505+
println!("{}", "--- not found errors (from test file) ---".red());
1506+
for error in &not_found {
1507+
println!("{}", error.render_for_expected());
1508+
}
1509+
println!("{}", "---\n".red());
15021510
}
1503-
panic!();
1511+
panic!("errors differ from expected");
15041512
}
15051513
}
15061514

@@ -3435,13 +3443,13 @@ impl<'test> TestCx<'test> {
34353443
// ```
34363444
// base_dir/
34373445
// rmake.exe
3438-
// scratch/
3446+
// rmake_out/
34393447
// ```
3440-
// having the executable separate from the scratch directory allows the recipes to
3441-
// `remove_dir_all(scratch)` without running into permission denied issues because
3442-
// the executable is not under the `scratch/` directory.
3448+
// having the executable separate from the output artifacts directory allows the recipes to
3449+
// `remove_dir_all($TMPDIR)` without running into permission denied issues because
3450+
// the executable is not under the `rmake_out/` directory.
34433451
//
3444-
// This setup diverges from legacy Makefile run-make tests.
3452+
// This setup intentionally diverges from legacy Makefile run-make tests.
34453453
let base_dir = cwd.join(self.output_base_name());
34463454
if base_dir.exists() {
34473455
self.aggressive_rm_rf(&base_dir).unwrap();

src/tools/run-make-support/src/lib.rs

+26-12
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,23 @@ pub fn dynamic_lib_name(name: &str) -> String {
123123
// ```
124124
assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
125125

126+
let extension = dynamic_lib_extension();
126127
if is_darwin() {
127-
format!("lib{name}.dylib")
128+
format!("lib{name}.{extension}")
128129
} else if is_windows() {
129-
format!("{name}.dll")
130+
format!("{name}.{extension}")
130131
} else {
131-
format!("lib{name}.so")
132+
format!("lib{name}.{extension}")
133+
}
134+
}
135+
136+
pub fn dynamic_lib_extension() -> &'static str {
137+
if is_darwin() {
138+
"dylib"
139+
} else if is_windows() {
140+
"dll"
141+
} else {
142+
"so"
132143
}
133144
}
134145

@@ -249,16 +260,13 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
249260
}
250261

251262
let dir2 = dir2.as_ref();
252-
for entry in fs::read_dir(dir1).unwrap() {
253-
let entry = entry.unwrap();
254-
let entry_name = entry.file_name();
255-
let path = entry.path();
256-
257-
if path.is_dir() {
258-
recursive_diff(&path, &dir2.join(entry_name));
263+
read_dir(dir1, |entry_path| {
264+
let entry_name = entry_path.file_name().unwrap();
265+
if entry_path.is_dir() {
266+
recursive_diff(&entry_path, &dir2.join(entry_name));
259267
} else {
260268
let path2 = dir2.join(entry_name);
261-
let file1 = read_file(&path);
269+
let file1 = read_file(&entry_path);
262270
let file2 = read_file(&path2);
263271

264272
// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
@@ -267,10 +275,16 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
267275
assert!(
268276
file1 == file2,
269277
"`{}` and `{}` have different content",
270-
path.display(),
278+
entry_path.display(),
271279
path2.display(),
272280
);
273281
}
282+
});
283+
}
284+
285+
pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
286+
for entry in fs::read_dir(dir).unwrap() {
287+
callback(&entry.unwrap().path());
274288
}
275289
}
276290

src/tools/tidy/src/allowed_run_make_makefiles.txt

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ run-make/bare-outfile/Makefile
66
run-make/branch-protection-check-IBT/Makefile
77
run-make/c-dynamic-dylib/Makefile
88
run-make/c-dynamic-rlib/Makefile
9-
run-make/c-link-to-rust-dylib/Makefile
109
run-make/c-static-dylib/Makefile
1110
run-make/c-static-rlib/Makefile
1211
run-make/c-unwind-abi-catch-lib-panic/Makefile

tests/run-make/c-link-to-rust-dylib/Makefile

-21
This file was deleted.

0 commit comments

Comments
 (0)