Skip to content
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

Rollup of 5 pull requests #125899

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 36 additions & 19 deletions library/core/src/num/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,25 +1030,42 @@ impl f32 {
/// ```
#[unstable(feature = "num_midpoint", issue = "110840")]
pub fn midpoint(self, other: f32) -> f32 {
const LO: f32 = f32::MIN_POSITIVE * 2.;
const HI: f32 = f32::MAX / 2.;

let (a, b) = (self, other);
let abs_a = a.abs_private();
let abs_b = b.abs_private();

if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
(a + b) / 2.
} else if abs_a < LO {
// Not safe to halve a
a + (b / 2.)
} else if abs_b < LO {
// Not safe to halve b
(a / 2.) + b
} else {
// Not safe to halve a and b
(a / 2.) + (b / 2.)
cfg_if! {
if #[cfg(any(
target_arch = "x86_64",
target_arch = "aarch64",
all(any(target_arch="riscv32", target_arch= "riscv64"), target_feature="d"),
all(target_arch = "arm", target_feature="vfp2"),
target_arch = "wasm32",
target_arch = "wasm64",
))] {
// whitelist the faster implementation to targets that have known good 64-bit float
// implementations. Falling back to the branchy code on targets that don't have
// 64-bit hardware floats or buggy implementations.
// see: https://github.com/rust-lang/rust/pull/121062#issuecomment-2123408114
((f64::from(self) + f64::from(other)) / 2.0) as f32
} else {
const LO: f32 = f32::MIN_POSITIVE * 2.;
const HI: f32 = f32::MAX / 2.;

let (a, b) = (self, other);
let abs_a = a.abs_private();
let abs_b = b.abs_private();

if abs_a <= HI && abs_b <= HI {
// Overflow is impossible
(a + b) / 2.
} else if abs_a < LO {
// Not safe to halve a
a + (b / 2.)
} else if abs_b < LO {
// Not safe to halve b
(a / 2.) + b
} else {
// Not safe to halve a and b
(a / 2.) + (b / 2.)
}
}
}
}

Expand Down
29 changes: 26 additions & 3 deletions library/core/tests/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ assume_usize_width! {
}

macro_rules! test_float {
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr) => {
($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
mod $modname {
#[test]
fn min() {
Expand Down Expand Up @@ -880,6 +880,27 @@ macro_rules! test_float {
assert!(($nan as $fty).midpoint(1.0).is_nan());
assert!((1.0 as $fty).midpoint($nan).is_nan());
assert!(($nan as $fty).midpoint($nan).is_nan());

// test if large differences in magnitude are still correctly computed.
// NOTE: that because of how small x and y are, x + y can never overflow
// so (x + y) / 2.0 is always correct
// in particular, `2.pow(i)` will never be at the max exponent, so it could
// be safely doubled, while j is significantly smaller.
for i in $max_exp.saturating_sub(64)..$max_exp {
for j in 0..64u8 {
let large = <$fty>::from(2.0f32).powi(i);
// a much smaller number, such that there is no chance of overflow to test
// potential double rounding in midpoint's implementation.
let small = <$fty>::from(2.0f32).powi($max_exp - 1)
* <$fty>::EPSILON
* <$fty>::from(j);

let naive = (large + small) / 2.0;
let midpoint = large.midpoint(small);

assert_eq!(naive, midpoint);
}
}
}
#[test]
fn rem_euclid() {
Expand Down Expand Up @@ -912,7 +933,8 @@ test_float!(
f32::NAN,
f32::MIN,
f32::MAX,
f32::MIN_POSITIVE
f32::MIN_POSITIVE,
f32::MAX_EXP
);
test_float!(
f64,
Expand All @@ -922,5 +944,6 @@ test_float!(
f64::NAN,
f64::MIN,
f64::MAX,
f64::MIN_POSITIVE
f64::MIN_POSITIVE,
f64::MAX_EXP
);
12 changes: 12 additions & 0 deletions src/tools/compiletest/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ pub struct Error {
pub msg: String,
}

impl Error {
pub fn render_for_expected(&self) -> String {
use colored::Colorize;
format!(
"{: <10}line {: >3}: {}",
self.kind.map(|kind| kind.to_string()).unwrap_or_default().to_uppercase(),
self.line_num,
self.msg.cyan(),
)
}
}

#[derive(PartialEq, Debug)]
enum WhichLine {
ThisLine,
Expand Down
10 changes: 9 additions & 1 deletion src/tools/compiletest/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::{env, sync::Arc};
use std::{env, io::IsTerminal, sync::Arc};

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

fn main() {
tracing_subscriber::fmt::init();

// colored checks stdout by default, but for some reason only stderr is a terminal.
// compiletest *does* print many things to stdout, but it doesn't really matter.
if std::io::stderr().is_terminal()
&& matches!(std::env::var("NO_COLOR").as_deref(), Err(_) | Ok("0"))
{
colored::control::set_override(true);
}

let config = Arc::new(parse_config(env::args().collect()));

if config.valgrind_path.is_none() && config.force_valgrind {
Expand Down
29 changes: 19 additions & 10 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ use crate::json;
use crate::read2::{read2_abbreviated, Truncated};
use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt};
use crate::ColorConfig;
use colored::Colorize;
use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
use regex::{Captures, Regex};
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};

use std::collections::{HashMap, HashSet};
use std::env;
use std::ffi::{OsStr, OsString};
Expand Down Expand Up @@ -1493,14 +1493,22 @@ impl<'test> TestCx<'test> {
unexpected.len(),
not_found.len()
));
println!("status: {}\ncommand: {}", proc_res.status, proc_res.cmdline);
println!("status: {}\ncommand: {}\n", proc_res.status, proc_res.cmdline);
if !unexpected.is_empty() {
println!("unexpected errors (from JSON output): {:#?}\n", unexpected);
println!("{}", "--- unexpected errors (from JSON output) ---".green());
for error in &unexpected {
println!("{}", error.render_for_expected());
}
println!("{}", "---".green());
}
if !not_found.is_empty() {
println!("not found errors (from test file): {:#?}\n", not_found);
println!("{}", "--- not found errors (from test file) ---".red());
for error in &not_found {
println!("{}", error.render_for_expected());
}
println!("{}", "---\n".red());
}
panic!();
panic!("errors differ from expected");
}
}

Expand Down Expand Up @@ -3369,6 +3377,7 @@ impl<'test> TestCx<'test> {
cmd.env("IS_MSVC", "1")
.env("IS_WINDOWS", "1")
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
.env("MSVC_LIB_PATH", format!("{}", lib.display()))
.env("CC", format!("'{}' {}", self.config.cc, cflags))
.env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
} else {
Expand Down Expand Up @@ -3435,13 +3444,13 @@ impl<'test> TestCx<'test> {
// ```
// base_dir/
// rmake.exe
// scratch/
// rmake_out/
// ```
// having the executable separate from the scratch directory allows the recipes to
// `remove_dir_all(scratch)` without running into permission denied issues because
// the executable is not under the `scratch/` directory.
// having the executable separate from the output artifacts directory allows the recipes to
// `remove_dir_all($TMPDIR)` without running into permission denied issues because
// the executable is not under the `rmake_out/` directory.
//
// This setup diverges from legacy Makefile run-make tests.
// This setup intentionally diverges from legacy Makefile run-make tests.
let base_dir = cwd.join(self.output_base_name());
if base_dir.exists() {
self.aggressive_rm_rf(&base_dir).unwrap();
Expand Down
82 changes: 70 additions & 12 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,23 @@ pub fn dynamic_lib_name(name: &str) -> String {
// ```
assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");

let extension = dynamic_lib_extension();
if is_darwin() {
format!("lib{name}.dylib")
format!("lib{name}.{extension}")
} else if is_windows() {
format!("{name}.dll")
format!("{name}.{extension}")
} else {
format!("lib{name}.so")
format!("lib{name}.{extension}")
}
}

pub fn dynamic_lib_extension() -> &'static str {
if is_darwin() {
"dylib"
} else if is_windows() {
"dll"
} else {
"so"
}
}

Expand All @@ -149,6 +160,50 @@ pub fn bin_name(name: &str) -> String {
if is_windows() { format!("{name}.exe") } else { name.to_string() }
}

fn ar<P: AsRef<str>, P2: AsRef<str>>(obj_path: P, lib_path: P2, caller_line_number: u32) {
let mut ar = Command::new(env::var("AR").unwrap());
ar.current_dir(tmp_dir()).arg("crus").arg(lib_path.as_ref()).arg(obj_path.as_ref());
let output = ar.output().unwrap();
if !output.status.success() {
handle_failed_output(&ar, output, caller_line_number);
}
}

/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
#[track_caller]
pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let obj_file = format!("{lib_name}.o");
let src = format!("{lib_name}.c");
let lib_name = if is_msvc() {
let lib_path = format!("lib{lib_name}.lib");
// First compiling `.c` to `.o`.
cc().arg("-c").out_exe(lib_name).input(src).run();
// Generating `.lib` from `.o`.
let mut msvc_lib = Command::new(env::var("MSVC_LIB_PATH").unwrap());
msvc_lib
.current_dir(tmp_dir())
.arg("-nologo")
.arg(&format!("-out:{}", cygpath_windows(&lib_path)))
.arg(&obj_file);
let output = msvc_lib.output().unwrap();
if !output.status.success() {
handle_failed_output(&msvc_lib, output, caller_line_number);
}
lib_path
} else {
let lib_path = format!("lib{lib_name}.a");
// First compiling `.c` to `.o`.
cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
// Generating `.a` from `.o`.
ar(obj_file, &lib_path, caller_line_number);
lib_path
};
tmp_dir().join(lib_name)
}

/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
/// available on the platform!
#[track_caller]
Expand Down Expand Up @@ -249,16 +304,13 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
}

let dir2 = dir2.as_ref();
for entry in fs::read_dir(dir1).unwrap() {
let entry = entry.unwrap();
let entry_name = entry.file_name();
let path = entry.path();

if path.is_dir() {
recursive_diff(&path, &dir2.join(entry_name));
read_dir(dir1, |entry_path| {
let entry_name = entry_path.file_name().unwrap();
if entry_path.is_dir() {
recursive_diff(&entry_path, &dir2.join(entry_name));
} else {
let path2 = dir2.join(entry_name);
let file1 = read_file(&path);
let file1 = read_file(&entry_path);
let file2 = read_file(&path2);

// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
Expand All @@ -267,10 +319,16 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
assert!(
file1 == file2,
"`{}` and `{}` have different content",
path.display(),
entry_path.display(),
path2.display(),
);
}
});
}

pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
for entry in fs::read_dir(dir).unwrap() {
callback(&entry.unwrap().path());
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/tools/run-make-support/src/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,11 @@ impl Rustc {
self
}

pub fn extra_filename(&mut self, extra: &str) -> &mut Self {
self.cmd.arg(format!("-Cextra-filename={extra}"));
self
}

/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
Expand Down
2 changes: 0 additions & 2 deletions src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ run-make/bare-outfile/Makefile
run-make/branch-protection-check-IBT/Makefile
run-make/c-dynamic-dylib/Makefile
run-make/c-dynamic-rlib/Makefile
run-make/c-link-to-rust-dylib/Makefile
run-make/c-static-dylib/Makefile
run-make/c-static-rlib/Makefile
run-make/c-unwind-abi-catch-lib-panic/Makefile
Expand Down Expand Up @@ -86,7 +85,6 @@ run-make/issue-107094/Makefile
run-make/issue-10971-temps-dir/Makefile
run-make/issue-109934-lto-debuginfo/Makefile
run-make/issue-14698/Makefile
run-make/issue-15460/Makefile
run-make/issue-18943/Makefile
run-make/issue-20626/Makefile
run-make/issue-22131/Makefile
Expand Down
21 changes: 0 additions & 21 deletions tests/run-make/c-link-to-rust-dylib/Makefile

This file was deleted.

Loading
Loading