From e00cbf304c1d3780718c60223e4650254c89818b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:21:18 +0000 Subject: [PATCH 01/22] Move std::env unit tests to integration tests --- library/std/src/env.rs | 3 - library/std/src/env/tests.rs | 120 ----------------------------------- library/std/tests/env.rs | 120 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 123 deletions(-) delete mode 100644 library/std/src/env/tests.rs diff --git a/library/std/src/env.rs b/library/std/src/env.rs index bbd506127fb67..c665dfd36247f 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -10,9 +10,6 @@ #![stable(feature = "env", since = "1.0.0")] -#[cfg(test)] -mod tests; - use crate::error::Error; use crate::ffi::{OsStr, OsString}; use crate::path::{Path, PathBuf}; diff --git a/library/std/src/env/tests.rs b/library/std/src/env/tests.rs deleted file mode 100644 index d021726106872..0000000000000 --- a/library/std/src/env/tests.rs +++ /dev/null @@ -1,120 +0,0 @@ -use super::*; - -#[test] -#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)] -fn test_self_exe_path() { - let path = current_exe(); - assert!(path.is_ok()); - let path = path.unwrap(); - - // Hard to test this function - assert!(path.is_absolute()); -} - -#[test] -fn test() { - assert!((!Path::new("test-path").is_absolute())); - - #[cfg(not(target_env = "sgx"))] - current_dir().unwrap(); -} - -#[test] -#[cfg(windows)] -fn split_paths_windows() { - use crate::path::PathBuf; - - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed).collect::>() - == parsed.iter().map(|s| PathBuf::from(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse(r#""""#, &mut [""])); - assert!(check_parse(";;", &mut ["", "", ""])); - assert!(check_parse(r"c:\", &mut [r"c:\"])); - assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); - assert!(check_parse(r"c:\;c:\Program Files\", &mut [r"c:\", r"c:\Program Files\"])); - assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); - assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); -} - -#[test] -#[cfg(unix)] -fn split_paths_unix() { - use crate::path::PathBuf; - - fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { - split_paths(unparsed).collect::>() - == parsed.iter().map(|s| PathBuf::from(*s)).collect::>() - } - - assert!(check_parse("", &mut [""])); - assert!(check_parse("::", &mut ["", "", ""])); - assert!(check_parse("/", &mut ["/"])); - assert!(check_parse("/:", &mut ["/", ""])); - assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); -} - -#[test] -#[cfg(unix)] -fn join_paths_unix() { - use crate::ffi::OsStr; - - fn test_eq(input: &[&str], output: &str) -> bool { - &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output) - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], "/bin:/usr/bin:/usr/local/bin")); - assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], ":/bin:::/usr/bin:")); - assert!(join_paths(["/te:st"].iter().cloned()).is_err()); -} - -#[test] -#[cfg(windows)] -fn join_paths_windows() { - use crate::ffi::OsStr; - - fn test_eq(input: &[&str], output: &str) -> bool { - &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output) - } - - assert!(test_eq(&[], "")); - assert!(test_eq(&[r"c:\windows", r"c:\"], r"c:\windows;c:\")); - assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], r";c:\windows;;;c:\;")); - assert!(test_eq(&[r"c:\te;st", r"c:\"], r#""c:\te;st";c:\"#)); - assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err()); -} - -#[test] -fn args_debug() { - assert_eq!( - format!("Args {{ inner: {:?} }}", args().collect::>()), - format!("{:?}", args()) - ); -} - -#[test] -fn args_os_debug() { - assert_eq!( - format!("ArgsOs {{ inner: {:?} }}", args_os().collect::>()), - format!("{:?}", args_os()) - ); -} - -#[test] -fn vars_debug() { - assert_eq!( - format!("Vars {{ inner: {:?} }}", vars().collect::>()), - format!("{:?}", vars()) - ); -} - -#[test] -fn vars_os_debug() { - assert_eq!( - format!("VarsOs {{ inner: {:?} }}", vars_os().collect::>()), - format!("{:?}", vars_os()) - ); -} diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 44fe84c989fb7..688c326a26aae 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -1,5 +1,6 @@ use std::env::*; use std::ffi::{OsStr, OsString}; +use std::path::Path; use rand::distributions::{Alphanumeric, DistString}; @@ -161,3 +162,122 @@ fn test_env_get_set_multithreaded() { let _ = getter.join(); let _ = setter.join(); } + +#[test] +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)] +fn test_self_exe_path() { + let path = current_exe(); + assert!(path.is_ok()); + let path = path.unwrap(); + + // Hard to test this function + assert!(path.is_absolute()); +} + +#[test] +fn test() { + assert!((!Path::new("test-path").is_absolute())); + + #[cfg(not(target_env = "sgx"))] + current_dir().unwrap(); +} + +#[test] +#[cfg(windows)] +fn split_paths_windows() { + use std::path::PathBuf; + + fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { + split_paths(unparsed).collect::>() + == parsed.iter().map(|s| PathBuf::from(*s)).collect::>() + } + + assert!(check_parse("", &mut [""])); + assert!(check_parse(r#""""#, &mut [""])); + assert!(check_parse(";;", &mut ["", "", ""])); + assert!(check_parse(r"c:\", &mut [r"c:\"])); + assert!(check_parse(r"c:\;", &mut [r"c:\", ""])); + assert!(check_parse(r"c:\;c:\Program Files\", &mut [r"c:\", r"c:\Program Files\"])); + assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"])); + assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#, &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"])); +} + +#[test] +#[cfg(unix)] +fn split_paths_unix() { + use std::path::PathBuf; + + fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { + split_paths(unparsed).collect::>() + == parsed.iter().map(|s| PathBuf::from(*s)).collect::>() + } + + assert!(check_parse("", &mut [""])); + assert!(check_parse("::", &mut ["", "", ""])); + assert!(check_parse("/", &mut ["/"])); + assert!(check_parse("/:", &mut ["/", ""])); + assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"])); +} + +#[test] +#[cfg(unix)] +fn join_paths_unix() { + use std::ffi::OsStr; + + fn test_eq(input: &[&str], output: &str) -> bool { + &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output) + } + + assert!(test_eq(&[], "")); + assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"], "/bin:/usr/bin:/usr/local/bin")); + assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""], ":/bin:::/usr/bin:")); + assert!(join_paths(["/te:st"].iter().cloned()).is_err()); +} + +#[test] +#[cfg(windows)] +fn join_paths_windows() { + use std::ffi::OsStr; + + fn test_eq(input: &[&str], output: &str) -> bool { + &*join_paths(input.iter().cloned()).unwrap() == OsStr::new(output) + } + + assert!(test_eq(&[], "")); + assert!(test_eq(&[r"c:\windows", r"c:\"], r"c:\windows;c:\")); + assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""], r";c:\windows;;;c:\;")); + assert!(test_eq(&[r"c:\te;st", r"c:\"], r#""c:\te;st";c:\"#)); + assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err()); +} + +#[test] +fn args_debug() { + assert_eq!( + format!("Args {{ inner: {:?} }}", args().collect::>()), + format!("{:?}", args()) + ); +} + +#[test] +fn args_os_debug() { + assert_eq!( + format!("ArgsOs {{ inner: {:?} }}", args_os().collect::>()), + format!("{:?}", args_os()) + ); +} + +#[test] +fn vars_debug() { + assert_eq!( + format!("Vars {{ inner: {:?} }}", vars().collect::>()), + format!("{:?}", vars()) + ); +} + +#[test] +fn vars_os_debug() { + assert_eq!( + format!("VarsOs {{ inner: {:?} }}", vars_os().collect::>()), + format!("{:?}", vars_os()) + ); +} From 03d44a641b61d4cad0cb025ffb1d6be7cd194ae7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:23:31 +0000 Subject: [PATCH 02/22] Move std::error unit tests to integration tests --- library/std/src/error.rs | 3 --- library/std/{src/error/tests.rs => tests/error.rs} | 10 ++++------ 2 files changed, 4 insertions(+), 9 deletions(-) rename library/std/{src/error/tests.rs => tests/error.rs} (98%) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index b3e63aaf1c567..def5f984c88e4 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -1,9 +1,6 @@ #![doc = include_str!("../../core/src/error.md")] #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(test)] -mod tests; - #[stable(feature = "rust1", since = "1.0.0")] pub use core::error::Error; #[unstable(feature = "error_generic_member_access", issue = "99301")] diff --git a/library/std/src/error/tests.rs b/library/std/tests/error.rs similarity index 98% rename from library/std/src/error/tests.rs rename to library/std/tests/error.rs index 88a9f33c07908..8fd6eb3c02065 100644 --- a/library/std/src/error/tests.rs +++ b/library/std/tests/error.rs @@ -1,7 +1,8 @@ -use core::error::Request; +#![feature(error_generic_member_access, error_reporter)] -use super::Error; -use crate::fmt; +use std::backtrace::Backtrace; +use std::error::{Error, Report, Request}; +use std::fmt; #[derive(Debug, PartialEq)] struct A; @@ -38,9 +39,6 @@ fn downcasting() { } } -use crate::backtrace::Backtrace; -use crate::error::Report; - #[derive(Debug)] struct SuperError { source: SuperErrorSideKick, From 29166cd61711776e6d43239d6d18a0eafe6515b1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:36:11 +0000 Subject: [PATCH 03/22] Move std float unit tests to integration tests --- library/std/Cargo.toml | 4 ++ library/std/src/f128.rs | 3 -- library/std/src/f16.rs | 3 -- library/std/src/f32.rs | 3 -- library/std/src/f64.rs | 3 -- library/std/src/macros.rs | 15 ------- library/std/src/num.rs | 25 ----------- .../f128/tests.rs => tests/floats/f128.rs} | 10 ++--- .../{src/f16/tests.rs => tests/floats/f16.rs} | 7 ++-- .../{src/f32/tests.rs => tests/floats/f32.rs} | 8 ++-- .../{src/f64/tests.rs => tests/floats/f64.rs} | 7 ++-- library/std/tests/floats/lib.rs | 42 +++++++++++++++++++ 12 files changed, 59 insertions(+), 71 deletions(-) rename library/std/{src/f128/tests.rs => tests/floats/f128.rs} (99%) rename library/std/{src/f16/tests.rs => tests/floats/f16.rs} (99%) rename library/std/{src/f32/tests.rs => tests/floats/f32.rs} (99%) rename library/std/{src/f64/tests.rs => tests/floats/f64.rs} (99%) create mode 100644 library/std/tests/floats/lib.rs diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index da58d7c13bd12..9c1b04b2742fd 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -130,6 +130,10 @@ name = "pipe-subprocess" path = "tests/pipe_subprocess.rs" harness = false +[[test]] +name = "floats" +path = "tests/floats/lib.rs" + [[bench]] name = "stdbenches" path = "benches/lib.rs" diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 4f37e18a8cd76..5a3626ccc1f3c 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -4,9 +4,6 @@ //! //! Mathematically significant numbers are provided in the `consts` sub-module. -#[cfg(test)] -mod tests; - #[unstable(feature = "f128", issue = "116909")] pub use core::f128::consts; diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index 42cd6e3fe2a5f..56b11ae170f8e 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -4,9 +4,6 @@ //! //! Mathematically significant numbers are provided in the `consts` sub-module. -#[cfg(test)] -mod tests; - #[unstable(feature = "f16", issue = "116909")] pub use core::f16::consts; diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 438d77b1626be..1842a079dbc84 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -12,9 +12,6 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#[cfg(test)] -mod tests; - #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::f32::{ diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 9bb4bfbab2a0f..cb62b2cc9df36 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -12,9 +12,6 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#[cfg(test)] -mod tests; - #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated, deprecated_in_future)] pub use core::f64::{ diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 1b0d7f3dbf2c9..e0f9f0bb5cee4 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -372,18 +372,3 @@ macro_rules! dbg { ($($crate::dbg!($val)),+,) }; } - -/// Verify that floats are within a tolerance of each other, 1.0e-6 by default. -#[cfg(test)] -macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; - ($a:expr, $b:expr, $lim:expr) => {{ - let (a, b) = (&$a, &$b); - let diff = (*a - *b).abs(); - assert!( - diff < $lim, - "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})", - lim = $lim - ); - }}; -} diff --git a/library/std/src/num.rs b/library/std/src/num.rs index d2f679e7dde54..dd76081532f55 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -29,28 +29,3 @@ pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError} pub use core::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize}; #[stable(feature = "nonzero", since = "1.28.0")] pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize}; - -#[cfg(test)] -use crate::fmt; -#[cfg(test)] -use crate::ops::{Add, Div, Mul, Rem, Sub}; - -/// Helper function for testing numeric operations -#[cfg(test)] -pub fn test_num(ten: T, two: T) -where - T: PartialEq - + Add - + Sub - + Mul - + Div - + Rem - + fmt::Debug - + Copy, -{ - assert_eq!(ten.add(two), ten + two); - assert_eq!(ten.sub(two), ten - two); - assert_eq!(ten.mul(two), ten * two); - assert_eq!(ten.div(two), ten / two); - assert_eq!(ten.rem(two), ten % two); -} diff --git a/library/std/src/f128/tests.rs b/library/std/tests/floats/f128.rs similarity index 99% rename from library/std/src/f128/tests.rs rename to library/std/tests/floats/f128.rs index cbcf9f96239bb..d0e8b157e6b6f 100644 --- a/library/std/src/f128/tests.rs +++ b/library/std/tests/floats/f128.rs @@ -1,11 +1,11 @@ // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(reliable_f128)] -use crate::f128::consts; -use crate::num::FpCategory as Fp; +use std::f128::consts; +use std::num::FpCategory as Fp; #[cfg(reliable_f128_math)] -use crate::ops::Rem; -use crate::ops::{Add, Div, Mul, Sub}; +use std::ops::Rem; +use std::ops::{Add, Div, Mul, Sub}; // Note these tolerances make sense around zero, but not for more extreme exponents. @@ -762,8 +762,6 @@ fn test_ln_gamma() { #[test] fn test_real_consts() { - use super::consts; - let pi: f128 = consts::PI; let frac_pi_2: f128 = consts::FRAC_PI_2; let frac_pi_3: f128 = consts::FRAC_PI_3; diff --git a/library/std/src/f16/tests.rs b/library/std/tests/floats/f16.rs similarity index 99% rename from library/std/src/f16/tests.rs rename to library/std/tests/floats/f16.rs index 684ee3f3855b8..5180f3d40f3a7 100644 --- a/library/std/src/f16/tests.rs +++ b/library/std/tests/floats/f16.rs @@ -1,8 +1,8 @@ // FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy #![cfg(reliable_f16)] -use crate::f16::consts; -use crate::num::{FpCategory as Fp, *}; +use std::f16::consts; +use std::num::FpCategory as Fp; /// Tolerance for results on the order of 10.0e-2 #[allow(unused)] @@ -54,7 +54,7 @@ macro_rules! assert_f16_biteq { #[test] fn test_num_f16() { - test_num(10f16, 2f16); + crate::test_num(10f16, 2f16); } #[test] @@ -734,7 +734,6 @@ fn test_ln_gamma() { #[test] fn test_real_consts() { // FIXME(f16_f128): add math tests when available - use super::consts; let pi: f16 = consts::PI; let frac_pi_2: f16 = consts::FRAC_PI_2; diff --git a/library/std/src/f32/tests.rs b/library/std/tests/floats/f32.rs similarity index 99% rename from library/std/src/f32/tests.rs rename to library/std/tests/floats/f32.rs index 99cfcfb231dad..bf7641986ada8 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/tests/floats/f32.rs @@ -1,5 +1,5 @@ -use crate::f32::consts; -use crate::num::{FpCategory as Fp, *}; +use std::f32::consts; +use std::num::FpCategory as Fp; /// Smallest number const TINY_BITS: u32 = 0x1; @@ -35,7 +35,7 @@ macro_rules! assert_f32_biteq { #[test] fn test_num_f32() { - test_num(10f32, 2f32); + crate::test_num(10f32, 2f32); } #[test] @@ -700,8 +700,6 @@ fn test_ln_gamma() { #[test] fn test_real_consts() { - use super::consts; - let pi: f32 = consts::PI; let frac_pi_2: f32 = consts::FRAC_PI_2; let frac_pi_3: f32 = consts::FRAC_PI_3; diff --git a/library/std/src/f64/tests.rs b/library/std/tests/floats/f64.rs similarity index 99% rename from library/std/src/f64/tests.rs rename to library/std/tests/floats/f64.rs index f5ba2c7b594e9..cbbfcd15efd26 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/tests/floats/f64.rs @@ -1,5 +1,5 @@ -use crate::f64::consts; -use crate::num::{FpCategory as Fp, *}; +use std::f64::consts; +use std::num::FpCategory as Fp; /// Smallest number const TINY_BITS: u64 = 0x1; @@ -35,7 +35,7 @@ macro_rules! assert_f64_biteq { #[test] fn test_num_f64() { - test_num(10f64, 2f64); + crate::test_num(10f64, 2f64); } #[test] @@ -680,7 +680,6 @@ fn test_ln_gamma() { #[test] fn test_real_consts() { - use super::consts; let pi: f64 = consts::PI; let frac_pi_2: f64 = consts::FRAC_PI_2; let frac_pi_3: f64 = consts::FRAC_PI_3; diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs new file mode 100644 index 0000000000000..79813871ed940 --- /dev/null +++ b/library/std/tests/floats/lib.rs @@ -0,0 +1,42 @@ +#![feature(f16, f128, float_gamma, float_next_up_down, float_minimum_maximum)] + +use std::fmt; +use std::ops::{Add, Div, Mul, Rem, Sub}; + +/// Verify that floats are within a tolerance of each other, 1.0e-6 by default. +macro_rules! assert_approx_eq { + ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; + ($a:expr, $b:expr, $lim:expr) => {{ + let (a, b) = (&$a, &$b); + let diff = (*a - *b).abs(); + assert!( + diff < $lim, + "{a:?} is not approximately equal to {b:?} (threshold {lim:?}, difference {diff:?})", + lim = $lim + ); + }}; +} + +/// Helper function for testing numeric operations +pub fn test_num(ten: T, two: T) +where + T: PartialEq + + Add + + Sub + + Mul + + Div + + Rem + + fmt::Debug + + Copy, +{ + assert_eq!(ten.add(two), ten + two); + assert_eq!(ten.sub(two), ten - two); + assert_eq!(ten.mul(two), ten * two); + assert_eq!(ten.div(two), ten / two); + assert_eq!(ten.rem(two), ten % two); +} + +mod f128; +mod f16; +mod f32; +mod f64; From 9baeb453095bc74966e0c99a6eeddefed5ed9eaa Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:37:50 +0000 Subject: [PATCH 04/22] Move std::num unit tests to integration tests --- library/std/src/num.rs | 3 --- library/std/{src/num/tests.rs => tests/num.rs} | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) rename library/std/{src/num/tests.rs => tests/num.rs} (98%) diff --git a/library/std/src/num.rs b/library/std/src/num.rs index dd76081532f55..ffb8789c906ef 100644 --- a/library/std/src/num.rs +++ b/library/std/src/num.rs @@ -6,9 +6,6 @@ #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] -#[cfg(test)] -mod tests; - #[stable(feature = "int_error_matching", since = "1.55.0")] pub use core::num::IntErrorKind; #[stable(feature = "generic_nonzero", since = "1.79.0")] diff --git a/library/std/src/num/tests.rs b/library/std/tests/num.rs similarity index 98% rename from library/std/src/num/tests.rs rename to library/std/tests/num.rs index df0df3f23f756..a7400f1c02df0 100644 --- a/library/std/src/num/tests.rs +++ b/library/std/tests/num.rs @@ -1,4 +1,4 @@ -use crate::ops::Mul; +use std::ops::Mul; #[test] fn test_saturating_add_uint() { @@ -190,8 +190,8 @@ fn test_uint_to_str_overflow() { assert_eq!(u64_val.to_string(), "0"); } -fn from_str(t: &str) -> Option { - crate::str::FromStr::from_str(t).ok() +fn from_str(t: &str) -> Option { + std::str::FromStr::from_str(t).ok() } #[test] From 09c4dbf7fbb545c0b861ea2473dcb84023f494c4 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:39:09 +0000 Subject: [PATCH 05/22] Move std::panic unit tests to integration tests --- library/std/src/panic.rs | 3 --- library/std/{src/panic/tests.rs => tests/panic.rs} | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) rename library/std/{src/panic/tests.rs => tests/panic.rs} (89%) diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index d649357a56d71..153189b8b0315 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -529,6 +529,3 @@ pub fn get_backtrace_style() -> Option { Err(new) => BacktraceStyle::from_u8(new), } } - -#[cfg(test)] -mod tests; diff --git a/library/std/src/panic/tests.rs b/library/std/tests/panic.rs similarity index 89% rename from library/std/src/panic/tests.rs rename to library/std/tests/panic.rs index b37d74011cc67..f13b931dd222e 100644 --- a/library/std/src/panic/tests.rs +++ b/library/std/tests/panic.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] -use crate::cell::RefCell; -use crate::panic::{AssertUnwindSafe, UnwindSafe}; -use crate::rc::Rc; -use crate::sync::{Arc, Mutex, RwLock}; +use std::cell::RefCell; +use std::panic::{AssertUnwindSafe, UnwindSafe}; +use std::rc::Rc; +use std::sync::{Arc, Mutex, RwLock}; struct Foo { a: i32, From b8fa843a1a60146b93ca5b1d11bbe23c1b1076f3 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:46:15 +0000 Subject: [PATCH 06/22] Move std::path unit tests to integration tests --- library/std/benches/lib.rs | 1 + library/std/benches/path.rs | 114 ++++++++++++++ library/std/src/path.rs | 3 - .../std/{src/path/tests.rs => tests/path.rs} | 149 +++--------------- 4 files changed, 139 insertions(+), 128 deletions(-) create mode 100644 library/std/benches/path.rs rename library/std/{src/path/tests.rs => tests/path.rs} (93%) diff --git a/library/std/benches/lib.rs b/library/std/benches/lib.rs index 1b21c230a0bf2..ae000d24d2816 100644 --- a/library/std/benches/lib.rs +++ b/library/std/benches/lib.rs @@ -5,3 +5,4 @@ extern crate test; mod hash; +mod path; diff --git a/library/std/benches/path.rs b/library/std/benches/path.rs new file mode 100644 index 0000000000000..094c00894a8ee --- /dev/null +++ b/library/std/benches/path.rs @@ -0,0 +1,114 @@ +use core::hint::black_box; +use std::collections::{BTreeSet, HashSet}; +use std::hash::{DefaultHasher, Hash, Hasher}; +use std::path::*; + +#[bench] +#[cfg_attr(miri, ignore)] // Miri isn't fast... +fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) { + let prefix = "my/home"; + let mut paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); + + paths.sort(); + + b.iter(|| { + black_box(paths.as_mut_slice()).sort_unstable(); + }); +} + +#[bench] +#[cfg_attr(miri, ignore)] // Miri isn't fast... +fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) { + let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); + + let mut set = BTreeSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + b.iter(|| { + set.remove(paths[500].as_path()); + set.insert(paths[500].as_path()); + }); +} + +#[bench] +#[cfg_attr(miri, ignore)] // Miri isn't fast... +fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) { + let prefix = "my/home"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); + + let mut set = BTreeSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + b.iter(|| { + set.remove(paths[500].as_path()); + set.insert(paths[500].as_path()); + }); +} + +#[bench] +#[cfg_attr(miri, ignore)] // Miri isn't fast... +fn bench_path_hashset(b: &mut test::Bencher) { + let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); + + let mut set = HashSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + b.iter(|| { + set.remove(paths[500].as_path()); + set.insert(black_box(paths[500].as_path())) + }); +} + +#[bench] +#[cfg_attr(miri, ignore)] // Miri isn't fast... +fn bench_path_hashset_miss(b: &mut test::Bencher) { + let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; + let paths: Vec<_> = + (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); + + let mut set = HashSet::new(); + + paths.iter().for_each(|p| { + set.insert(p.as_path()); + }); + + let probe = PathBuf::from(prefix).join("other"); + + b.iter(|| set.remove(black_box(probe.as_path()))); +} + +#[bench] +fn bench_hash_path_short(b: &mut test::Bencher) { + let mut hasher = DefaultHasher::new(); + let path = Path::new("explorer.exe"); + + b.iter(|| black_box(path).hash(&mut hasher)); + + black_box(hasher.finish()); +} + +#[bench] +fn bench_hash_path_long(b: &mut test::Bencher) { + let mut hasher = DefaultHasher::new(); + let path = + Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff"); + + b.iter(|| black_box(path).hash(&mut hasher)); + + black_box(hasher.finish()); +} diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 7fd08a97f1f20..97e17acadeac7 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -67,9 +67,6 @@ #![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] -#[cfg(test)] -mod tests; - use core::clone::CloneToUninit; use crate::borrow::{Borrow, Cow}; diff --git a/library/std/src/path/tests.rs b/library/std/tests/path.rs similarity index 93% rename from library/std/src/path/tests.rs rename to library/std/tests/path.rs index 3f96ac4672aff..978402b6fdaea 100644 --- a/library/std/src/path/tests.rs +++ b/library/std/tests/path.rs @@ -1,10 +1,19 @@ -use core::hint::black_box; - -use super::*; -use crate::collections::{BTreeSet, HashSet}; -use crate::hash::DefaultHasher; -use crate::mem::MaybeUninit; -use crate::ptr; +#![feature( + clone_to_uninit, + path_add_extension, + path_file_prefix, + maybe_uninit_slice, + os_string_pathbuf_leak +)] + +use std::clone::CloneToUninit; +use std::ffi::OsStr; +use std::hash::{DefaultHasher, Hash, Hasher}; +use std::mem::MaybeUninit; +use std::path::*; +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; #[allow(unknown_lints, unused_macro_rules)] macro_rules! t ( @@ -110,7 +119,7 @@ macro_rules! t ( #[test] fn into() { - use crate::borrow::Cow; + use std::borrow::Cow; let static_path = Path::new("/home/foo"); let static_cow_path: Cow<'static, Path> = static_path.into(); @@ -1525,7 +1534,7 @@ pub fn test_with_added_extension() { #[test] fn test_eq_receivers() { - use crate::borrow::Cow; + use std::borrow::Cow; let borrowed: &Path = Path::new("foo/bar"); let mut owned: PathBuf = PathBuf::new(); @@ -1550,7 +1559,7 @@ fn test_eq_receivers() { #[test] pub fn test_compare() { - use crate::hash::{DefaultHasher, Hash, Hasher}; + use std::hash::{DefaultHasher, Hash, Hasher}; fn hash(t: T) -> u64 { let mut s = DefaultHasher::new(); @@ -1867,12 +1876,12 @@ fn test_ord() { #[test] #[cfg(any(unix, target_os = "wasi"))] fn test_unix_absolute() { - use crate::path::absolute; + use std::path::absolute; assert!(absolute("").is_err()); let relative = "a/b"; - let mut expected = crate::env::current_dir().unwrap(); + let mut expected = std::env::current_dir().unwrap(); expected.push(relative); assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str()); @@ -1888,7 +1897,7 @@ fn test_unix_absolute() { ); // Test leading `.` and `..` components - let curdir = crate::env::current_dir().unwrap(); + let curdir = std::env::current_dir().unwrap(); assert_eq!(absolute("./a").unwrap().as_os_str(), curdir.join("a").as_os_str()); assert_eq!(absolute("../a").unwrap().as_os_str(), curdir.join("../a").as_os_str()); // return /pwd/../a } @@ -1896,12 +1905,12 @@ fn test_unix_absolute() { #[test] #[cfg(windows)] fn test_windows_absolute() { - use crate::path::absolute; + use std::path::absolute; // An empty path is an error. assert!(absolute("").is_err()); let relative = r"a\b"; - let mut expected = crate::env::current_dir().unwrap(); + let mut expected = std::env::current_dir().unwrap(); expected.push(relative); assert_eq!(absolute(relative).unwrap().as_os_str(), expected.as_os_str()); @@ -1953,116 +1962,6 @@ fn test_extension_path_sep_alternate() { assert_eq!(path, Path::new("path/to/file.d\\test")); } -#[bench] -#[cfg_attr(miri, ignore)] // Miri isn't fast... -fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) { - let prefix = "my/home"; - let mut paths: Vec<_> = - (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); - - paths.sort(); - - b.iter(|| { - black_box(paths.as_mut_slice()).sort_unstable(); - }); -} - -#[bench] -#[cfg_attr(miri, ignore)] // Miri isn't fast... -fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) { - let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; - let paths: Vec<_> = - (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); - - let mut set = BTreeSet::new(); - - paths.iter().for_each(|p| { - set.insert(p.as_path()); - }); - - b.iter(|| { - set.remove(paths[500].as_path()); - set.insert(paths[500].as_path()); - }); -} - -#[bench] -#[cfg_attr(miri, ignore)] // Miri isn't fast... -fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) { - let prefix = "my/home"; - let paths: Vec<_> = - (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); - - let mut set = BTreeSet::new(); - - paths.iter().for_each(|p| { - set.insert(p.as_path()); - }); - - b.iter(|| { - set.remove(paths[500].as_path()); - set.insert(paths[500].as_path()); - }); -} - -#[bench] -#[cfg_attr(miri, ignore)] // Miri isn't fast... -fn bench_path_hashset(b: &mut test::Bencher) { - let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; - let paths: Vec<_> = - (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); - - let mut set = HashSet::new(); - - paths.iter().for_each(|p| { - set.insert(p.as_path()); - }); - - b.iter(|| { - set.remove(paths[500].as_path()); - set.insert(black_box(paths[500].as_path())) - }); -} - -#[bench] -#[cfg_attr(miri, ignore)] // Miri isn't fast... -fn bench_path_hashset_miss(b: &mut test::Bencher) { - let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/"; - let paths: Vec<_> = - (0..1000).map(|num| PathBuf::from(prefix).join(format!("file {num}.rs"))).collect(); - - let mut set = HashSet::new(); - - paths.iter().for_each(|p| { - set.insert(p.as_path()); - }); - - let probe = PathBuf::from(prefix).join("other"); - - b.iter(|| set.remove(black_box(probe.as_path()))); -} - -#[bench] -fn bench_hash_path_short(b: &mut test::Bencher) { - let mut hasher = DefaultHasher::new(); - let path = Path::new("explorer.exe"); - - b.iter(|| black_box(path).hash(&mut hasher)); - - black_box(hasher.finish()); -} - -#[bench] -fn bench_hash_path_long(b: &mut test::Bencher) { - let mut hasher = DefaultHasher::new(); - let path = - Path::new("/aaaaa/aaaaaa/./../aaaaaaaa/bbbbbbbbbbbbb/ccccccccccc/ddddddddd/eeeeeee.fff"); - - b.iter(|| black_box(path).hash(&mut hasher)); - - black_box(hasher.finish()); -} - #[test] fn clone_to_uninit() { let a = Path::new("hello.txt"); From 4ce917dfd5182d78c7351092473de1960efc9626 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:49:46 +0000 Subject: [PATCH 07/22] Move std::time unit tests to integration tests --- library/std/benches/lib.rs | 1 + library/std/benches/time.rs | 47 ++++++++++++++++ library/std/src/time.rs | 3 - .../std/{src/time/tests.rs => tests/time.rs} | 55 ++----------------- 4 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 library/std/benches/time.rs rename library/std/{src/time/tests.rs => tests/time.rs} (81%) diff --git a/library/std/benches/lib.rs b/library/std/benches/lib.rs index ae000d24d2816..e749d9c0f7998 100644 --- a/library/std/benches/lib.rs +++ b/library/std/benches/lib.rs @@ -6,3 +6,4 @@ extern crate test; mod hash; mod path; +mod time; diff --git a/library/std/benches/time.rs b/library/std/benches/time.rs new file mode 100644 index 0000000000000..552481cad928a --- /dev/null +++ b/library/std/benches/time.rs @@ -0,0 +1,47 @@ +use std::time::Instant; + +#[cfg(not(target_arch = "wasm32"))] +use test::{Bencher, black_box}; + +macro_rules! bench_instant_threaded { + ($bench_name:ident, $thread_count:expr) => { + #[bench] + #[cfg(not(target_arch = "wasm32"))] + fn $bench_name(b: &mut Bencher) -> std::thread::Result<()> { + use std::sync::Arc; + use std::sync::atomic::{AtomicBool, Ordering}; + + let running = Arc::new(AtomicBool::new(true)); + + let threads: Vec<_> = (0..$thread_count) + .map(|_| { + let flag = Arc::clone(&running); + std::thread::spawn(move || { + while flag.load(Ordering::Relaxed) { + black_box(Instant::now()); + } + }) + }) + .collect(); + + b.iter(|| { + let a = Instant::now(); + let b = Instant::now(); + assert!(b >= a); + }); + + running.store(false, Ordering::Relaxed); + + for t in threads { + t.join()?; + } + Ok(()) + } + }; +} + +bench_instant_threaded!(instant_contention_01_threads, 0); +bench_instant_threaded!(instant_contention_02_threads, 1); +bench_instant_threaded!(instant_contention_04_threads, 3); +bench_instant_threaded!(instant_contention_08_threads, 7); +bench_instant_threaded!(instant_contention_16_threads, 15); diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 9f4f8a0d0880c..88b3e9e0ceba0 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -31,9 +31,6 @@ #![stable(feature = "time", since = "1.3.0")] -#[cfg(test)] -mod tests; - #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; #[stable(feature = "duration_checked_float", since = "1.66.0")] diff --git a/library/std/src/time/tests.rs b/library/std/tests/time.rs similarity index 81% rename from library/std/src/time/tests.rs rename to library/std/tests/time.rs index e88f2d5e80676..40709eae37cfc 100644 --- a/library/std/src/time/tests.rs +++ b/library/std/tests/time.rs @@ -1,9 +1,7 @@ -use core::fmt::Debug; +#![feature(duration_constants)] -#[cfg(not(target_arch = "wasm32"))] -use test::{Bencher, black_box}; - -use super::{Duration, Instant, SystemTime, UNIX_EPOCH}; +use std::fmt::Debug; +use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH}; macro_rules! assert_almost_eq { ($a:expr, $b:expr) => {{ @@ -29,10 +27,10 @@ fn instant_monotonic() { #[test] #[cfg(not(target_arch = "wasm32"))] -fn instant_monotonic_concurrent() -> crate::thread::Result<()> { +fn instant_monotonic_concurrent() -> std::thread::Result<()> { let threads: Vec<_> = (0..8) .map(|_| { - crate::thread::spawn(|| { + std::thread::spawn(|| { let mut old = Instant::now(); let count = if cfg!(miri) { 1_000 } else { 5_000_000 }; for _ in 0..count { @@ -229,46 +227,3 @@ fn big_math() { check(instant.checked_add(Duration::from_secs(100)), Instant::checked_sub); check(instant.checked_add(Duration::from_secs(i64::MAX as _)), Instant::checked_sub); } - -macro_rules! bench_instant_threaded { - ($bench_name:ident, $thread_count:expr) => { - #[bench] - #[cfg(not(target_arch = "wasm32"))] - fn $bench_name(b: &mut Bencher) -> crate::thread::Result<()> { - use crate::sync::Arc; - use crate::sync::atomic::{AtomicBool, Ordering}; - - let running = Arc::new(AtomicBool::new(true)); - - let threads: Vec<_> = (0..$thread_count) - .map(|_| { - let flag = Arc::clone(&running); - crate::thread::spawn(move || { - while flag.load(Ordering::Relaxed) { - black_box(Instant::now()); - } - }) - }) - .collect(); - - b.iter(|| { - let a = Instant::now(); - let b = Instant::now(); - assert!(b >= a); - }); - - running.store(false, Ordering::Relaxed); - - for t in threads { - t.join()?; - } - Ok(()) - } - }; -} - -bench_instant_threaded!(instant_contention_01_threads, 0); -bench_instant_threaded!(instant_contention_02_threads, 1); -bench_instant_threaded!(instant_contention_04_threads, 3); -bench_instant_threaded!(instant_contention_08_threads, 7); -bench_instant_threaded!(instant_contention_16_threads, 15); From 332fb7e6f1d3fd4df628a9d772c47e7e0c387e0f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 10:25:12 +0000 Subject: [PATCH 08/22] Move std::thread_local unit tests to integration tests --- library/std/Cargo.toml | 4 ++++ library/std/src/thread/local.rs | 6 ------ .../local => tests/thread_local}/dynamic_tests.rs | 6 +++--- library/std/tests/thread_local/lib.rs | 4 ++++ .../{src/thread/local => tests/thread_local}/tests.rs | 10 +++++----- 5 files changed, 16 insertions(+), 14 deletions(-) rename library/std/{src/thread/local => tests/thread_local}/dynamic_tests.rs (89%) create mode 100644 library/std/tests/thread_local/lib.rs rename library/std/{src/thread/local => tests/thread_local}/tests.rs (98%) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 9c1b04b2742fd..be6c2aad8713f 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -134,6 +134,10 @@ harness = false name = "floats" path = "tests/floats/lib.rs" +[[test]] +name = "thread_local" +path = "tests/thread_local/lib.rs" + [[bench]] name = "stdbenches" path = "benches/lib.rs" diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index c003503ca8b09..ca04aa4ada497 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -2,12 +2,6 @@ #![unstable(feature = "thread_local_internals", issue = "none")] -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -#[cfg(test)] -mod dynamic_tests; - use crate::cell::{Cell, RefCell}; use crate::error::Error; use crate::fmt; diff --git a/library/std/src/thread/local/dynamic_tests.rs b/library/std/tests/thread_local/dynamic_tests.rs similarity index 89% rename from library/std/src/thread/local/dynamic_tests.rs rename to library/std/tests/thread_local/dynamic_tests.rs index dd18004164824..454462b392510 100644 --- a/library/std/src/thread/local/dynamic_tests.rs +++ b/library/std/tests/thread_local/dynamic_tests.rs @@ -1,6 +1,6 @@ -use crate::cell::RefCell; -use crate::collections::HashMap; -use crate::thread_local; +use std::cell::RefCell; +use std::collections::HashMap; +use std::thread_local; #[test] fn smoke() { diff --git a/library/std/tests/thread_local/lib.rs b/library/std/tests/thread_local/lib.rs new file mode 100644 index 0000000000000..c52914354253c --- /dev/null +++ b/library/std/tests/thread_local/lib.rs @@ -0,0 +1,4 @@ +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod tests; + +mod dynamic_tests; diff --git a/library/std/src/thread/local/tests.rs b/library/std/tests/thread_local/tests.rs similarity index 98% rename from library/std/src/thread/local/tests.rs rename to library/std/tests/thread_local/tests.rs index 9d4f52a09218e..aa020c2559cc5 100644 --- a/library/std/src/thread/local/tests.rs +++ b/library/std/tests/thread_local/tests.rs @@ -1,8 +1,8 @@ -use crate::cell::{Cell, UnsafeCell}; -use crate::sync::atomic::{AtomicU8, Ordering}; -use crate::sync::{Arc, Condvar, Mutex}; -use crate::thread::{self, Builder, LocalKey}; -use crate::thread_local; +use std::cell::{Cell, UnsafeCell}; +use std::sync::atomic::{AtomicU8, Ordering}; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread::{self, Builder, LocalKey}; +use std::thread_local; #[derive(Clone, Default)] struct Signal(Arc<(Mutex, Condvar)>); From b8ae372e483ed194a4aff2c4500bb7f0fd7e2967 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 11:04:40 +0000 Subject: [PATCH 09/22] Move std::sync unit tests to integration tests This removes two minor OnceLock tests which test private methods. The rest of the tests should be more than enough to catch mistakes in those private methods. Also makes ReentrantLock::try_lock public. And finally it makes the mpmc tests actually run. --- library/std/Cargo.toml | 4 +++ library/std/src/sync/barrier.rs | 3 -- library/std/src/sync/lazy_lock.rs | 3 -- library/std/src/sync/{mpsc/mod.rs => mpsc.rs} | 13 +++----- library/std/src/sync/once_lock.rs | 3 -- library/std/src/sync/poison/condvar.rs | 3 -- library/std/src/sync/poison/mutex.rs | 3 -- library/std/src/sync/poison/once.rs | 3 -- library/std/src/sync/poison/rwlock.rs | 3 -- library/std/src/sync/reentrant_lock.rs | 8 ++--- .../tests.rs => tests/sync/barrier.rs} | 6 ++-- .../tests.rs => tests/sync/condvar.rs} | 10 +++--- .../tests.rs => tests/sync/lazy_lock.rs} | 12 +++---- library/std/tests/sync/lib.rs | 32 +++++++++++++++++++ .../sync/mpmc/tests.rs => tests/sync/mpmc.rs} | 5 +-- .../sync/mpsc/tests.rs => tests/sync/mpsc.rs} | 5 +-- .../sync_tests.rs => tests/sync/mpsc_sync.rs} | 9 +++--- .../mutex/tests.rs => tests/sync/mutex.rs} | 14 ++++---- .../once/tests.rs => tests/sync/once.rs} | 12 +++---- .../tests.rs => tests/sync/once_lock.rs} | 20 +++--------- .../tests.rs => tests/sync/reentrant_lock.rs} | 7 ++-- .../rwlock/tests.rs => tests/sync/rwlock.rs} | 22 ++++++------- 22 files changed, 101 insertions(+), 99 deletions(-) rename library/std/src/sync/{mpsc/mod.rs => mpsc.rs} (99%) rename library/std/{src/sync/barrier/tests.rs => tests/sync/barrier.rs} (89%) rename library/std/{src/sync/poison/condvar/tests.rs => tests/sync/condvar.rs} (97%) rename library/std/{src/sync/lazy_lock/tests.rs => tests/sync/lazy_lock.rs} (93%) create mode 100644 library/std/tests/sync/lib.rs rename library/std/{src/sync/mpmc/tests.rs => tests/sync/mpmc.rs} (99%) rename library/std/{src/sync/mpsc/tests.rs => tests/sync/mpsc.rs} (99%) rename library/std/{src/sync/mpsc/sync_tests.rs => tests/sync/mpsc_sync.rs} (99%) rename library/std/{src/sync/poison/mutex/tests.rs => tests/sync/mutex.rs} (97%) rename library/std/{src/sync/poison/once/tests.rs => tests/sync/once.rs} (94%) rename library/std/{src/sync/once_lock/tests.rs => tests/sync/once_lock.rs} (92%) rename library/std/{src/sync/reentrant_lock/tests.rs => tests/sync/reentrant_lock.rs} (91%) rename library/std/{src/sync/poison/rwlock/tests.rs => tests/sync/rwlock.rs} (98%) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index be6c2aad8713f..7648dc141d8c1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -130,6 +130,10 @@ name = "pipe-subprocess" path = "tests/pipe_subprocess.rs" harness = false +[[test]] +name = "sync" +path = "tests/sync/lib.rs" + [[test]] name = "floats" path = "tests/floats/lib.rs" diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 862753e4765dc..067ff66d9af73 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -1,6 +1,3 @@ -#[cfg(test)] -mod tests; - use crate::fmt; // FIXME(nonpoison_mutex,nonpoison_condvar): switch to nonpoison versions once they are available use crate::sync::{Condvar, Mutex}; diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 98c83d8d326ca..78cf8841efefb 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -350,6 +350,3 @@ unsafe impl Sync for LazyLock {} impl RefUnwindSafe for LazyLock {} #[stable(feature = "lazy_cell", since = "1.80.0")] impl UnwindSafe for LazyLock {} - -#[cfg(test)] -mod tests; diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc.rs similarity index 99% rename from library/std/src/sync/mpsc/mod.rs rename to library/std/src/sync/mpsc.rs index c86b546e01169..f942937c14d11 100644 --- a/library/std/src/sync/mpsc/mod.rs +++ b/library/std/src/sync/mpsc.rs @@ -137,12 +137,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod sync_tests; - // MPSC channels are built as a wrapper around MPMC channels, which // were ported from the `crossbeam-channel` crate. MPMC channels are // not exposed publicly, but if you are curious about the implementation, @@ -737,9 +731,10 @@ impl SyncSender { // Attempts to send for a value on this receiver, returning an error if the // corresponding channel has hung up, or if it waits more than `timeout`. // - // This method is currently private and only used for tests. - #[allow(unused)] - fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError> { + // This method is currently only used for tests. + #[unstable(issue = "none", feature = "std_internals")] + #[doc(hidden)] + pub fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError> { self.inner.send_timeout(t, timeout) } } diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 49f2dafd8fd9c..f6e4b34a13a32 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -676,6 +676,3 @@ unsafe impl<#[may_dangle] T> Drop for OnceLock { } } } - -#[cfg(test)] -mod tests; diff --git a/library/std/src/sync/poison/condvar.rs b/library/std/src/sync/poison/condvar.rs index a6e2389c93baf..7f0f3f652bcb7 100644 --- a/library/std/src/sync/poison/condvar.rs +++ b/library/std/src/sync/poison/condvar.rs @@ -1,6 +1,3 @@ -#[cfg(test)] -mod tests; - use crate::fmt; use crate::sync::poison::{self, LockResult, MutexGuard, PoisonError, mutex}; use crate::sys::sync as sys; diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 01ef71a187fec..0a5ad56192655 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -1,6 +1,3 @@ -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - use crate::cell::UnsafeCell; use crate::fmt; use crate::marker::PhantomData; diff --git a/library/std/src/sync/poison/once.rs b/library/std/src/sync/poison/once.rs index 27db4b634fb28..f78d88ac6d896 100644 --- a/library/std/src/sync/poison/once.rs +++ b/library/std/src/sync/poison/once.rs @@ -3,9 +3,6 @@ //! This primitive is meant to be used to run one-time initialization. An //! example use case would be for initializing an FFI library. -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - use crate::fmt; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::sys::sync as sys; diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index 1519baf99a8fd..f9d9321f5f2d8 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -1,6 +1,3 @@ -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - use crate::cell::UnsafeCell; use crate::fmt; use crate::marker::PhantomData; diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 0140e0d21299f..e009eb410efc0 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -1,6 +1,3 @@ -#[cfg(all(test, not(any(target_os = "emscripten", target_os = "wasi"))))] -mod tests; - use cfg_if::cfg_if; use crate::cell::UnsafeCell; @@ -324,7 +321,10 @@ impl ReentrantLock { /// Otherwise, an RAII guard is returned. /// /// This function does not block. - pub(crate) fn try_lock(&self) -> Option> { + // FIXME maybe make it a public part of the API? + #[unstable(issue = "none", feature = "std_internals")] + #[doc(hidden)] + pub fn try_lock(&self) -> Option> { let this_thread = current_id(); // Safety: We only touch lock_count when we own the inner mutex. // Additionally, we only call `self.owner.set()` while holding diff --git a/library/std/src/sync/barrier/tests.rs b/library/std/tests/sync/barrier.rs similarity index 89% rename from library/std/src/sync/barrier/tests.rs rename to library/std/tests/sync/barrier.rs index 0fbcd9988127b..8aefff9d5071c 100644 --- a/library/std/src/sync/barrier/tests.rs +++ b/library/std/tests/sync/barrier.rs @@ -1,6 +1,6 @@ -use crate::sync::mpsc::{TryRecvError, channel}; -use crate::sync::{Arc, Barrier}; -use crate::thread; +use std::sync::mpsc::{TryRecvError, channel}; +use std::sync::{Arc, Barrier}; +use std::thread; #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads diff --git a/library/std/src/sync/poison/condvar/tests.rs b/library/std/tests/sync/condvar.rs similarity index 97% rename from library/std/src/sync/poison/condvar/tests.rs rename to library/std/tests/sync/condvar.rs index f9e9066bc92a2..834de6bb1c295 100644 --- a/library/std/src/sync/poison/condvar/tests.rs +++ b/library/std/tests/sync/condvar.rs @@ -1,8 +1,8 @@ -use crate::sync::atomic::{AtomicBool, Ordering}; -use crate::sync::mpsc::channel; -use crate::sync::{Arc, Condvar, Mutex}; -use crate::thread; -use crate::time::Duration; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc::channel; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread; +use std::time::Duration; #[test] fn smoke() { diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/tests/sync/lazy_lock.rs similarity index 93% rename from library/std/src/sync/lazy_lock/tests.rs rename to library/std/tests/sync/lazy_lock.rs index 7d7dde5434990..6c14b79f2ce7c 100644 --- a/library/std/src/sync/lazy_lock/tests.rs +++ b/library/std/tests/sync/lazy_lock.rs @@ -1,8 +1,8 @@ -use crate::cell::LazyCell; -use crate::sync::atomic::AtomicUsize; -use crate::sync::atomic::Ordering::SeqCst; -use crate::sync::{LazyLock, Mutex, OnceLock}; -use crate::{panic, thread}; +use std::cell::LazyCell; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; +use std::sync::{LazyLock, Mutex, OnceLock}; +use std::{panic, thread}; fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { thread::spawn(f).join().unwrap() @@ -149,7 +149,7 @@ fn is_sync_send() { #[should_panic = "has previously been poisoned"] fn lazy_force_mut_panic() { let mut lazy = LazyLock::::new(|| panic!()); - crate::panic::catch_unwind(crate::panic::AssertUnwindSafe(|| { + panic::catch_unwind(panic::AssertUnwindSafe(|| { let _ = LazyLock::force_mut(&mut lazy); })) .unwrap_err(); diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs new file mode 100644 index 0000000000000..6bf320d52f21a --- /dev/null +++ b/library/std/tests/sync/lib.rs @@ -0,0 +1,32 @@ +#![feature(lazy_get)] +#![feature(mapped_lock_guards)] +#![feature(mpmc_channel)] +#![feature(once_cell_try)] +#![feature(once_wait)] +#![feature(lock_value_accessors)] +#![feature(reentrant_lock)] +#![feature(rwlock_downgrade)] +#![feature(std_internals)] +#![allow(internal_features)] + +mod barrier; +mod condvar; +mod lazy_lock; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod mpmc; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod mpsc; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod mpsc_sync; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod mutex; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod once; +mod once_lock; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod reentrant_lock; +#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] +mod rwlock; + +#[path = "../common/mod.rs"] +mod common; diff --git a/library/std/src/sync/mpmc/tests.rs b/library/std/tests/sync/mpmc.rs similarity index 99% rename from library/std/src/sync/mpmc/tests.rs rename to library/std/tests/sync/mpmc.rs index ab14050df6c98..81b92297f76a3 100644 --- a/library/std/src/sync/mpmc/tests.rs +++ b/library/std/tests/sync/mpmc.rs @@ -1,5 +1,6 @@ -use super::*; -use crate::{env, thread}; +use std::sync::mpmc::*; +use std::time::{Duration, Instant}; +use std::{env, thread}; pub fn stress_factor() -> usize { match env::var("RUST_TEST_STRESS") { diff --git a/library/std/src/sync/mpsc/tests.rs b/library/std/tests/sync/mpsc.rs similarity index 99% rename from library/std/src/sync/mpsc/tests.rs rename to library/std/tests/sync/mpsc.rs index 13892fa0d18e4..1d8edfde44bed 100644 --- a/library/std/src/sync/mpsc/tests.rs +++ b/library/std/tests/sync/mpsc.rs @@ -1,5 +1,6 @@ -use super::*; -use crate::{env, thread}; +use std::sync::mpsc::*; +use std::time::{Duration, Instant}; +use std::{env, thread}; pub fn stress_factor() -> usize { match env::var("RUST_TEST_STRESS") { diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/tests/sync/mpsc_sync.rs similarity index 99% rename from library/std/src/sync/mpsc/sync_tests.rs rename to library/std/tests/sync/mpsc_sync.rs index 49b65c8efe692..a7f326d201b00 100644 --- a/library/std/src/sync/mpsc/sync_tests.rs +++ b/library/std/tests/sync/mpsc_sync.rs @@ -1,7 +1,8 @@ -use super::*; -use crate::rc::Rc; -use crate::sync::mpmc::SendTimeoutError; -use crate::{env, thread}; +use std::rc::Rc; +use std::sync::mpmc::SendTimeoutError; +use std::sync::mpsc::*; +use std::time::Duration; +use std::{env, thread}; pub fn stress_factor() -> usize { match env::var("RUST_TEST_STRESS") { diff --git a/library/std/src/sync/poison/mutex/tests.rs b/library/std/tests/sync/mutex.rs similarity index 97% rename from library/std/src/sync/poison/mutex/tests.rs rename to library/std/tests/sync/mutex.rs index 395c8aada089a..74c627201073e 100644 --- a/library/std/src/sync/poison/mutex/tests.rs +++ b/library/std/tests/sync/mutex.rs @@ -1,10 +1,10 @@ -use crate::fmt::Debug; -use crate::ops::FnMut; -use crate::panic::{self, AssertUnwindSafe}; -use crate::sync::atomic::{AtomicUsize, Ordering}; -use crate::sync::mpsc::channel; -use crate::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard, TryLockError}; -use crate::{hint, mem, thread}; +use std::fmt::Debug; +use std::ops::FnMut; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::channel; +use std::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard, TryLockError}; +use std::{hint, mem, thread}; struct Packet(Arc<(Mutex, Condvar)>); diff --git a/library/std/src/sync/poison/once/tests.rs b/library/std/tests/sync/once.rs similarity index 94% rename from library/std/src/sync/poison/once/tests.rs rename to library/std/tests/sync/once.rs index ce96468aeb6e1..a3ffc73fe06b9 100644 --- a/library/std/src/sync/poison/once/tests.rs +++ b/library/std/tests/sync/once.rs @@ -1,9 +1,9 @@ -use super::Once; -use crate::sync::atomic::AtomicBool; -use crate::sync::atomic::Ordering::Relaxed; -use crate::sync::mpsc::channel; -use crate::time::Duration; -use crate::{panic, thread}; +use std::sync::Once; +use std::sync::atomic::AtomicBool; +use std::sync::atomic::Ordering::Relaxed; +use std::sync::mpsc::channel; +use std::time::Duration; +use std::{panic, thread}; #[test] fn smoke_once() { diff --git a/library/std/src/sync/once_lock/tests.rs b/library/std/tests/sync/once_lock.rs similarity index 92% rename from library/std/src/sync/once_lock/tests.rs rename to library/std/tests/sync/once_lock.rs index 5113d436c3c99..1ce273b5a7a40 100644 --- a/library/std/src/sync/once_lock/tests.rs +++ b/library/std/tests/sync/once_lock.rs @@ -1,8 +1,8 @@ -use crate::sync::OnceLock; -use crate::sync::atomic::AtomicUsize; -use crate::sync::atomic::Ordering::SeqCst; -use crate::sync::mpsc::channel; -use crate::{panic, thread}; +use std::sync::OnceLock; +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering::SeqCst; +use std::sync::mpsc::channel; +use std::{panic, thread}; fn spawn_and_wait(f: impl FnOnce() -> R + Send + 'static) -> R { thread::spawn(f).join().unwrap() @@ -33,15 +33,6 @@ fn sync_once_cell_get_mut() { assert_eq!(c.get_mut(), Some(&mut 92)); } -#[test] -fn sync_once_cell_get_unchecked() { - let c = OnceLock::new(); - c.set(92).unwrap(); - unsafe { - assert_eq!(c.get_unchecked(), &92); - } -} - #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads fn sync_once_cell_drop() { @@ -88,7 +79,6 @@ fn get_or_try_init() { let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); assert!(res.is_err()); - assert!(!cell.is_initialized()); assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); diff --git a/library/std/src/sync/reentrant_lock/tests.rs b/library/std/tests/sync/reentrant_lock.rs similarity index 91% rename from library/std/src/sync/reentrant_lock/tests.rs rename to library/std/tests/sync/reentrant_lock.rs index aeef0289d28f8..2b7b87e36234a 100644 --- a/library/std/src/sync/reentrant_lock/tests.rs +++ b/library/std/tests/sync/reentrant_lock.rs @@ -1,7 +1,6 @@ -use super::ReentrantLock; -use crate::cell::RefCell; -use crate::sync::Arc; -use crate::thread; +use std::cell::RefCell; +use std::sync::{Arc, ReentrantLock}; +use std::thread; #[test] fn smoke() { diff --git a/library/std/src/sync/poison/rwlock/tests.rs b/library/std/tests/sync/rwlock.rs similarity index 98% rename from library/std/src/sync/poison/rwlock/tests.rs rename to library/std/tests/sync/rwlock.rs index 057c2f1a5d7a7..bd4bc7a14bc8e 100644 --- a/library/std/src/sync/poison/rwlock/tests.rs +++ b/library/std/tests/sync/rwlock.rs @@ -1,15 +1,15 @@ -use rand::Rng; - -use crate::fmt::Debug; -use crate::ops::FnMut; -use crate::panic::{self, AssertUnwindSafe}; -use crate::sync::atomic::{AtomicUsize, Ordering}; -use crate::sync::mpsc::channel; -use crate::sync::{ +use std::fmt::Debug; +use std::ops::FnMut; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::mpsc::channel; +use std::sync::{ Arc, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, TryLockError, }; -use crate::{hint, mem, thread}; +use std::{hint, mem, thread}; + +use rand::Rng; #[derive(Eq, PartialEq, Debug)] struct NonCopy(i32); @@ -57,7 +57,7 @@ fn frob() { let tx = tx.clone(); let r = r.clone(); thread::spawn(move || { - let mut rng = crate::test_helpers::test_rng(); + let mut rng = crate::common::test_rng(); for _ in 0..M { if rng.gen_bool(1.0 / (N as f64)) { drop(r.write().unwrap()); @@ -704,7 +704,7 @@ fn test_downgrade_atomic() { // Wait for a good amount of time so that evil threads go to sleep. // Note: this is not strictly necessary... - let eternity = crate::time::Duration::from_millis(42); + let eternity = std::time::Duration::from_millis(42); thread::sleep(eternity); // Once everyone is asleep, set the value to `NEW_VALUE`. From e76d0b819302dffe04ce40de6bf8be1ac0eca0c9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:35:50 +0000 Subject: [PATCH 10/22] Fix benchmarking of libstd --- library/std/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 7648dc141d8c1..67c249d54a046 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/rust.git" description = "The Rust Standard Library" edition = "2021" +autobenches = false [lib] crate-type = ["dylib", "rlib"] From 52907d713a5e47581361f5de9c7e72905b1f7348 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:23:19 +0000 Subject: [PATCH 11/22] Fix for SGX --- library/std/tests/sync/once_lock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/tests/sync/once_lock.rs b/library/std/tests/sync/once_lock.rs index 1ce273b5a7a40..ac9aaa8892eff 100644 --- a/library/std/tests/sync/once_lock.rs +++ b/library/std/tests/sync/once_lock.rs @@ -164,7 +164,7 @@ fn sync_once_cell_does_not_leak_partially_constructed_boxes() { break; } #[cfg(target_env = "sgx")] - crate::thread::yield_now(); + std::thread::yield_now(); } }); } From 05cbf03d8f98ca23bff64ea40925df3029d0dd89 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:29:05 +0000 Subject: [PATCH 12/22] Move env modifying tests to a separate integration test --- library/std/tests/env.rs | 160 ------------------------------ library/std/tests/env_modify.rs | 166 ++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 160 deletions(-) create mode 100644 library/std/tests/env_modify.rs diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs index 688c326a26aae..e754cf8263b0f 100644 --- a/library/std/tests/env.rs +++ b/library/std/tests/env.rs @@ -1,167 +1,7 @@ use std::env::*; -use std::ffi::{OsStr, OsString}; use std::path::Path; -use rand::distributions::{Alphanumeric, DistString}; - mod common; -use std::thread; - -use common::test_rng; - -#[track_caller] -fn make_rand_name() -> OsString { - let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10)); - let n = OsString::from(n); - assert!(var_os(&n).is_none()); - n -} - -fn eq(a: Option, b: Option<&str>) { - assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); -} - -#[test] -fn test_set_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - eq(var_os(&n), Some("VALUE")); -} - -#[test] -fn test_remove_var() { - let n = make_rand_name(); - set_var(&n, "VALUE"); - remove_var(&n); - eq(var_os(&n), None); -} - -#[test] -fn test_set_var_overwrite() { - let n = make_rand_name(); - set_var(&n, "1"); - set_var(&n, "2"); - eq(var_os(&n), Some("2")); - set_var(&n, ""); - eq(var_os(&n), Some("")); -} - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] -fn test_var_big() { - let mut s = "".to_string(); - let mut i = 0; - while i < 100 { - s.push_str("aaaaaaaaaa"); - i += 1; - } - let n = make_rand_name(); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); -} - -#[test] -#[cfg_attr(target_os = "emscripten", ignore)] -fn test_env_set_get_huge() { - let n = make_rand_name(); - let s = "x".repeat(10000); - set_var(&n, &s); - eq(var_os(&n), Some(&s)); - remove_var(&n); - eq(var_os(&n), None); -} - -#[test] -fn test_env_set_var() { - let n = make_rand_name(); - - let mut e = vars_os(); - set_var(&n, "VALUE"); - assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" })); - - assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" })); -} - -#[test] -#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))] -#[allow(deprecated)] -fn env_home_dir() { - use std::path::PathBuf; - - fn var_to_os_string(var: Result) -> Option { - match var { - Ok(var) => Some(OsString::from(var)), - Err(VarError::NotUnicode(var)) => Some(var), - _ => None, - } - } - - cfg_if::cfg_if! { - if #[cfg(unix)] { - let oldhome = var_to_os_string(var("HOME")); - - set_var("HOME", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - remove_var("HOME"); - if cfg!(target_os = "android") { - assert!(home_dir().is_none()); - } else { - // When HOME is not set, some platforms return `None`, - // but others return `Some` with a default. - // Just check that it is not "/home/MountainView". - assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - } - - if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } - } else if #[cfg(windows)] { - let oldhome = var_to_os_string(var("HOME")); - let olduserprofile = var_to_os_string(var("USERPROFILE")); - - remove_var("HOME"); - remove_var("USERPROFILE"); - - assert!(home_dir().is_some()); - - set_var("HOME", "/home/PaloAlto"); - assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used"); - - set_var("USERPROFILE", "/home/MountainView"); - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - remove_var("HOME"); - - assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); - - set_var("USERPROFILE", ""); - assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored"); - - remove_var("USERPROFILE"); - - if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } - if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); } - } - } -} - -#[test] // miri shouldn't detect any data race in this fn -#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)] -fn test_env_get_set_multithreaded() { - let getter = thread::spawn(|| { - for _ in 0..100 { - let _ = var_os("foo"); - } - }); - - let setter = thread::spawn(|| { - for _ in 0..100 { - set_var("foo", "bar"); - } - }); - - let _ = getter.join(); - let _ = setter.join(); -} #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi", target_env = "sgx"), ignore)] diff --git a/library/std/tests/env_modify.rs b/library/std/tests/env_modify.rs new file mode 100644 index 0000000000000..6074744735005 --- /dev/null +++ b/library/std/tests/env_modify.rs @@ -0,0 +1,166 @@ +// These tests are in a separate integration test as they modify the environment, +// and would otherwise cause some other tests to fail. + +use std::env::*; +use std::ffi::{OsStr, OsString}; + +use rand::distributions::{Alphanumeric, DistString}; + +mod common; +use std::thread; + +use common::test_rng; + +#[track_caller] +fn make_rand_name() -> OsString { + let n = format!("TEST{}", Alphanumeric.sample_string(&mut test_rng(), 10)); + let n = OsString::from(n); + assert!(var_os(&n).is_none()); + n +} + +fn eq(a: Option, b: Option<&str>) { + assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s)); +} + +#[test] +fn test_set_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + eq(var_os(&n), Some("VALUE")); +} + +#[test] +fn test_remove_var() { + let n = make_rand_name(); + set_var(&n, "VALUE"); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_set_var_overwrite() { + let n = make_rand_name(); + set_var(&n, "1"); + set_var(&n, "2"); + eq(var_os(&n), Some("2")); + set_var(&n, ""); + eq(var_os(&n), Some("")); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_var_big() { + let mut s = "".to_string(); + let mut i = 0; + while i < 100 { + s.push_str("aaaaaaaaaa"); + i += 1; + } + let n = make_rand_name(); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); +} + +#[test] +#[cfg_attr(target_os = "emscripten", ignore)] +fn test_env_set_get_huge() { + let n = make_rand_name(); + let s = "x".repeat(10000); + set_var(&n, &s); + eq(var_os(&n), Some(&s)); + remove_var(&n); + eq(var_os(&n), None); +} + +#[test] +fn test_env_set_var() { + let n = make_rand_name(); + + let mut e = vars_os(); + set_var(&n, "VALUE"); + assert!(!e.any(|(k, v)| { &*k == &*n && &*v == "VALUE" })); + + assert!(vars_os().any(|(k, v)| { &*k == &*n && &*v == "VALUE" })); +} + +#[test] +#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))] +#[allow(deprecated)] +fn env_home_dir() { + use std::path::PathBuf; + + fn var_to_os_string(var: Result) -> Option { + match var { + Ok(var) => Some(OsString::from(var)), + Err(VarError::NotUnicode(var)) => Some(var), + _ => None, + } + } + + cfg_if::cfg_if! { + if #[cfg(unix)] { + let oldhome = var_to_os_string(var("HOME")); + + set_var("HOME", "/home/MountainView"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + remove_var("HOME"); + if cfg!(target_os = "android") { + assert!(home_dir().is_none()); + } else { + // When HOME is not set, some platforms return `None`, + // but others return `Some` with a default. + // Just check that it is not "/home/MountainView". + assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + } + + if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } + } else if #[cfg(windows)] { + let oldhome = var_to_os_string(var("HOME")); + let olduserprofile = var_to_os_string(var("USERPROFILE")); + + remove_var("HOME"); + remove_var("USERPROFILE"); + + assert!(home_dir().is_some()); + + set_var("HOME", "/home/PaloAlto"); + assert_ne!(home_dir(), Some(PathBuf::from("/home/PaloAlto")), "HOME must not be used"); + + set_var("USERPROFILE", "/home/MountainView"); + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + remove_var("HOME"); + + assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView"))); + + set_var("USERPROFILE", ""); + assert_ne!(home_dir(), Some(PathBuf::from("")), "Empty USERPROFILE must be ignored"); + + remove_var("USERPROFILE"); + + if let Some(oldhome) = oldhome { set_var("HOME", oldhome); } + if let Some(olduserprofile) = olduserprofile { set_var("USERPROFILE", olduserprofile); } + } + } +} + +#[test] // miri shouldn't detect any data race in this fn +#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)] +fn test_env_get_set_multithreaded() { + let getter = thread::spawn(|| { + for _ in 0..100 { + let _ = var_os("foo"); + } + }); + + let setter = thread::spawn(|| { + for _ in 0..100 { + set_var("foo", "bar"); + } + }); + + let _ = getter.join(); + let _ = setter.join(); +} From a063cf5f1c151873f753905c75d8e67115308f9d Mon Sep 17 00:00:00 2001 From: "Alexis (Poliorcetics) Bourget" Date: Thu, 26 Dec 2024 23:41:58 +0100 Subject: [PATCH 13/22] fix(rustdoc): always use a channel when linking to doc.rust-lang.org --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/utils.rs | 6 +++--- src/librustdoc/core.rs | 2 +- src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/render/context.rs | 4 ++-- src/librustdoc/html/render/mod.rs | 4 ++-- src/librustdoc/html/render/print_item.rs | 2 +- src/librustdoc/html/static/js/main.js | 16 ++++++++-------- src/librustdoc/html/static/js/search.js | 9 +++++---- src/librustdoc/html/templates/type_layout.html | 2 +- .../html/templates/type_layout_size.html | 2 +- src/librustdoc/lib.rs | 4 ++-- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- tests/rustdoc/type-layout.rs | 4 ++-- 14 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7853e311a040c..f13428fc4203c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1934,7 +1934,7 @@ fn can_elide_trait_object_lifetime_bound<'tcx>( preds: &'tcx ty::List>, tcx: TyCtxt<'tcx>, ) -> bool { - // Below we quote extracts from https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes + // Below we quote extracts from https://doc.rust-lang.org/stable/reference/lifetime-elision.html#default-trait-object-lifetimes // > If the trait object is used as a type argument of a generic type then the containing type is // > first used to try to infer a bound. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 77040aeb94d77..65722eff1dab8 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -590,9 +590,9 @@ pub(crate) fn attrs_have_doc_flag<'a>( /// so that the channel is consistent. /// /// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable. -pub(crate) const DOC_RUST_LANG_ORG_CHANNEL: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); -pub(crate) static DOC_CHANNEL: Lazy<&'static str> = - Lazy::new(|| DOC_RUST_LANG_ORG_CHANNEL.rsplit('/').find(|c| !c.is_empty()).unwrap()); +pub(crate) const DOC_RUST_LANG_ORG_VERSION: &str = env!("DOC_RUST_LANG_ORG_CHANNEL"); +pub(crate) static RUSTDOC_VERSION: Lazy<&'static str> = + Lazy::new(|| DOC_RUST_LANG_ORG_VERSION.rsplit('/').find(|c| !c.is_empty()).unwrap()); /// Render a sequence of macro arms in a format suitable for displaying to the user /// as part of an item declaration. diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0437ebb585768..d6b2b53d34cbc 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -387,7 +387,7 @@ pub(crate) fn run_global_ctxt( let help = format!( "The following guide may be of use:\n\ {}/rustdoc/how-to-write-documentation.html", - crate::DOC_RUST_LANG_ORG_CHANNEL + crate::DOC_RUST_LANG_ORG_VERSION ); tcx.node_lint( crate::lint::MISSING_CRATE_LEVEL_DOCS, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index b4bc0b80d6c66..d957cf1b569e3 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -112,7 +112,7 @@ pub(crate) fn render( display_krate_with_trailing_slash, display_krate_version_number, display_krate_version_extra, - rust_channel: *crate::clean::utils::DOC_CHANNEL, + rust_channel: *crate::clean::utils::RUSTDOC_VERSION, rustdoc_version, } .render() diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 5d96dbc0ee659..1cefdf96bbcd2 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -32,7 +32,7 @@ use crate::html::render::write_shared::write_shared; use crate::html::url_parts_builder::UrlPartsBuilder; use crate::html::{layout, sources, static_files}; use crate::scrape_examples::AllCallLocations; -use crate::try_err; +use crate::{DOC_RUST_LANG_ORG_VERSION, try_err}; /// Major driving force in all rustdoc rendering. This contains information /// about where in the tree-like hierarchy rendering is occurring and controls @@ -730,7 +730,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { ", ) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a27a9d202eb80..f7dcb87e4f3d0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -79,7 +79,7 @@ use crate::html::markdown::{ use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD; use crate::html::{highlight, sources}; use crate::scrape_examples::{CallData, CallLocation}; -use crate::{DOC_RUST_LANG_ORG_CHANNEL, try_none}; +use crate::{DOC_RUST_LANG_ORG_VERSION, try_none}; pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { fmt::from_fn(move |f| { @@ -480,7 +480,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { content.push_str(&format!( "## More information\n\n\ If you want more information about this feature, please read the [corresponding chapter in \ - the Rustdoc book]({DOC_RUST_LANG_ORG_CHANNEL}/rustdoc/scraped-examples.html)." + the Rustdoc book]({DOC_RUST_LANG_ORG_VERSION}/rustdoc/scraped-examples.html)." )); let mut ids = IdMap::default(); diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 37fea09ace310..c50adf116160a 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -924,7 +924,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra dyn compatible.

\

In older versions of Rust, dyn compatibility was called \"object safety\", \ so this trait is not object safe.

", - base = crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL + base = crate::clean::utils::DOC_RUST_LANG_ORG_VERSION ), ); } diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index ccf4002bb300d..bfd5cb7764fd4 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1534,10 +1534,10 @@ function preLoadCss(cssUrl) { function buildHelpMenu() { const book_info = document.createElement("span"); - const channel = getVar("channel"); + const drloChannel = `https://doc.rust-lang.org/${getVar("channel")}`; book_info.className = "top"; book_info.innerHTML = `You can find more information in \ -the rustdoc book.`; +the rustdoc book.`; const shortcuts = [ ["?", "Show this help dialog"], @@ -1557,8 +1557,8 @@ function preLoadCss(cssUrl) { div_shortcuts.innerHTML = "

Keyboard Shortcuts

" + shortcuts + "
"; const infos = [ - `For a full list of all search features, take a look here.`, + `For a full list of all search features, take a look \ + here.`, "Prefix searches with a type followed by a colon (e.g., fn:) to \ restrict the search to a given item kind.", "Accepted kinds are: fn, mod, struct, \ @@ -1568,10 +1568,10 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm -> vec or String, enum:Cow -> bool)", "You can look for items with an exact name by putting double quotes around \ your request: \"string\"", - "Look for functions that accept or return \ - slices and \ - arrays by writing \ - square brackets (e.g., -> [u8] or [] -> Option)", + `Look for functions that accept or return \ + slices and \ + arrays by writing square \ + brackets (e.g., -> [u8] or [] -> Option)`, "Look for items inside another one by searching for a path: vec::Vec", ].map(x => "

" + x + "

").join(""); const div_infos = document.createElement("div"); diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 1ad32721e0687..662e951069973 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1,5 +1,5 @@ // ignore-tidy-filelength -/* global addClass, getNakedUrl, getSettingValue */ +/* global addClass, getNakedUrl, getSettingValue, getVar */ /* global onEachLazy, removeClass, searchState, browserSupportsHistoryApi, exports */ "use strict"; @@ -4923,17 +4923,18 @@ ${item.displayPath}${name}\ } }); } else if (query.error === null) { + const dlroChannel = `https://doc.rust-lang.org/${getVar("channel")}`; output.className = "search-failed" + extraClass; output.innerHTML = "No results :(
" + "Try on DuckDuckGo?

" + "Or try looking in one of these:"; diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 9c62826ccc2e3..0034552bdd3b7 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -10,7 +10,7 @@

{# #} unstable and may even differ between compilations. {#+ #} The only exception is types with certain repr(...) {#+ #} attributes. Please see the Rust Reference's {#+ #} - “Type Layout” {#+ #} + “Type Layout” {#+ #} chapter for details on type layout guarantees. {# #}

{# #} {# #} diff --git a/src/librustdoc/html/templates/type_layout_size.html b/src/librustdoc/html/templates/type_layout_size.html index 9c2b39edc9f37..5256b6c8f2ace 100644 --- a/src/librustdoc/html/templates/type_layout_size.html +++ b/src/librustdoc/html/templates/type_layout_size.html @@ -7,6 +7,6 @@ {{ size +}} bytes {% endif %} {% if is_uninhabited %} - {# +#} (uninhabited) + {# +#} (uninhabited) {% endif %} {% endif %} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bb954a31891ad..45f42e61fbf7a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -82,7 +82,7 @@ use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_opti use rustc_session::{EarlyDiagCtxt, getopts}; use tracing::info; -use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL; +use crate::clean::utils::DOC_RUST_LANG_ORG_VERSION; /// A macro to create a FxHashMap. /// @@ -710,7 +710,7 @@ fn usage(argv0: &str) { println!("{}", options.usage(&format!("{argv0} [options] "))); println!(" @path Read newline separated options from `path`\n"); println!( - "More information available at {DOC_RUST_LANG_ORG_CHANNEL}/rustdoc/what-is-rustdoc.html", + "More information available at {DOC_RUST_LANG_ORG_VERSION}/rustdoc/what-is-rustdoc.html", ); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index a777b45b8070b..9fe8b99e8af87 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -2168,7 +2168,7 @@ fn disambiguator_error( report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp, _link_range| { let msg = format!( "see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators", - crate::DOC_RUST_LANG_ORG_CHANNEL + crate::DOC_RUST_LANG_ORG_VERSION ); diag.note(msg); }); diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs index 5f34c8b99e0ff..6de435dbcc143 100644 --- a/tests/rustdoc/type-layout.rs +++ b/tests/rustdoc/type-layout.rs @@ -86,11 +86,11 @@ pub enum WithNiche { } //@ hasraw type_layout/enum.Uninhabited.html 'Size: ' -//@ hasraw - '0 bytes (uninhabited)' +//@ hasraw - '0 bytes (uninhabited)' pub enum Uninhabited {} //@ hasraw type_layout/struct.Uninhabited2.html 'Size: ' -//@ hasraw - '8 bytes (uninhabited)' +//@ hasraw - '8 bytes (uninhabited)' pub struct Uninhabited2(std::convert::Infallible, u64); pub trait Project { type Assoc; } From 5efee2c55e480980e72ceab6e88ca1b44fb7420c Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 25 Dec 2024 22:24:30 -0500 Subject: [PATCH 14/22] Enable more tests on Windows --- tests/codegen/debug-column.rs | 2 +- tests/codegen/force-no-unwind-tables.rs | 2 +- tests/codegen/thread-local.rs | 2 +- tests/crashes/132981.rs | 4 ++++ .../relative-path-include-bytes-132203.rs | 2 +- tests/ui-fulldeps/stable-mir/check_abi.rs | 1 - .../ui-fulldeps/stable-mir/check_allocation.rs | 1 - .../ui-fulldeps/stable-mir/check_attribute.rs | 1 - tests/ui-fulldeps/stable-mir/check_binop.rs | 1 - .../ui-fulldeps/stable-mir/check_crate_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_def_ty.rs | 1 - tests/ui-fulldeps/stable-mir/check_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_foreign.rs | 1 - tests/ui-fulldeps/stable-mir/check_instance.rs | 1 - .../ui-fulldeps/stable-mir/check_intrinsics.rs | 1 - .../ui-fulldeps/stable-mir/check_item_kind.rs | 1 - .../stable-mir/check_normalization.rs | 1 - .../stable-mir/check_trait_queries.rs | 1 - .../ui-fulldeps/stable-mir/check_transform.rs | 1 - tests/ui-fulldeps/stable-mir/check_ty_fold.rs | 1 - .../stable-mir/compilation-result.rs | 1 - tests/ui-fulldeps/stable-mir/crate-info.rs | 1 - tests/ui-fulldeps/stable-mir/projections.rs | 1 - tests/ui-fulldeps/stable-mir/smir_internal.rs | 1 - tests/ui-fulldeps/stable-mir/smir_serde.rs | 1 - tests/ui-fulldeps/stable-mir/smir_visitor.rs | 1 - tests/ui/abi/abi-sysv64-arg-passing.rs | 3 ++- tests/ui/abi/large-byval-align.rs | 1 - .../feature-gate-cfg-target-thread-local.rs | 2 +- tests/ui/inference/issue-71584.rs | 2 +- ...age-attr-does-not-panic-llvm-issue-33992.rs | 3 ++- .../propagate-generic-issue-18804/main.rs | 1 - tests/ui/logging-only-prints-once.rs | 1 - tests/ui/lto/weak-works.rs | 3 ++- tests/ui/parser/mod_file_not_exist.rs | 2 -- tests/ui/parser/mod_file_not_exist.stderr | 4 ++-- .../suggestions/missing-lifetime-specifier.rs | 1 - .../missing-lifetime-specifier.stderr | 18 +++++++++--------- .../ui/threads-sendsync/spawning-with-debug.rs | 1 - .../thread-local-extern-static.rs | 2 +- tests/ui/traits/issue-77982.rs | 3 +-- tests/ui/traits/issue-77982.stderr | 14 +++++++------- tests/ui/typeck/issue-43189.rs | 1 - tests/ui/typeck/issue-43189.stderr | 2 +- tests/ui/typeck/issue-46112.rs | 1 - tests/ui/typeck/issue-46112.stderr | 4 ++-- 46 files changed, 39 insertions(+), 63 deletions(-) diff --git a/tests/codegen/debug-column.rs b/tests/codegen/debug-column.rs index d14a5c29142eb..2aa0a8a864ca1 100644 --- a/tests/codegen/debug-column.rs +++ b/tests/codegen/debug-column.rs @@ -1,6 +1,6 @@ // Verify that debuginfo column numbers are 1-based byte offsets. // -//@ ignore-windows +//@ ignore-msvc //@ compile-flags: -C debuginfo=2 #[rustfmt::skip] diff --git a/tests/codegen/force-no-unwind-tables.rs b/tests/codegen/force-no-unwind-tables.rs index e823bedac0f64..1de5e0858e0ba 100644 --- a/tests/codegen/force-no-unwind-tables.rs +++ b/tests/codegen/force-no-unwind-tables.rs @@ -1,5 +1,5 @@ //@ compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n -//@ ignore-windows +//@ ignore-windows: unwind tables are required for panics on Windows #![crate_type = "lib"] diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs index 2ee15811cc3d5..3cd81652f5ace 100644 --- a/tests/codegen/thread-local.rs +++ b/tests/codegen/thread-local.rs @@ -1,6 +1,6 @@ //@ compile-flags: -O //@ aux-build:thread_local_aux.rs -//@ ignore-windows FIXME(#84933) +//@ ignore-windows FIXME(#134939) //@ ignore-wasm globals are used instead of thread locals //@ ignore-emscripten globals are used instead of thread locals //@ ignore-android does not use #[thread_local] diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs index 8ff4fa36fd071..916c15592404c 100644 --- a/tests/crashes/132981.rs +++ b/tests/crashes/132981.rs @@ -2,6 +2,10 @@ //@compile-flags: -Clink-dead-code=true --crate-type lib //@ only-x86_64 //@ ignore-windows +// The set of targets this crashes on is really fiddly, because it is deep in our ABI logic. It +// crashes on x86_64-unknown-linux-gnu, and i686-pc-windows-msvc, but not on +// x86_64-pc-windows-msvc. If you are trying to fix this crash, don't pay too much attention to the +// directives. #![feature(rust_cold_cc)] pub extern "rust-cold" fn foo(_: [usize; 3]) {} diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs index 5c9e2978e48a6..6fddaa49faced 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs @@ -1,4 +1,4 @@ -//@ ignore-windows +//@ ignore-windows different error message //@ revisions: edition2015 edition2024 //@[edition2015]edition:2015 //@[edition2015]check-fail diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 8caf3032afc44..ef2d5b4854bef 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 072c8ba6a442c..c102f86a2286b 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs index 22481e275a99f..11cb63f3f8a58 100644 --- a/tests/ui-fulldeps/stable-mir/check_attribute.rs +++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs index 8c44e28510843..65b3ffd27ab05 100644 --- a/tests/ui-fulldeps/stable-mir/check_binop.rs +++ b/tests/ui-fulldeps/stable-mir/check_binop.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs index ed093903381b2..71cca94c34f62 100644 --- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs index 482dbd22d5fe2..37b9a83e33e76 100644 --- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs +++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index bf1f1a2ceab98..cd3d76d876012 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs index 4acbabbb6be1d..bc3956b309088 100644 --- a/tests/ui-fulldeps/stable-mir/check_foreign.rs +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 464350b104571..72a138f907e72 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index 6edebaf756c56..2f772b978865a 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -8,7 +8,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 23b54e6c60b39..647ce534589e1 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs index 928173b154b4f..de14202adb9c0 100644 --- a/tests/ui-fulldeps/stable-mir/check_normalization.rs +++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index 304a7ce925554..23c2844d3f166 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index bcf79c456b073..d9fc924933fa8 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index e21508c9b4612..9fa4929d68e27 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index d921de73f4364..b8a9e720e5465 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 53be8eb10c1ed..7f0e9b50335d3 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index fdb7eeed1b0e5..3cc71247e6744 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index 6f5478c08bf9b..453e5372de4f8 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs index 7dbf892f9e4b1..2c74276d550cf 100644 --- a/tests/ui-fulldeps/stable-mir/smir_serde.rs +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 666000d3b070f..0a6415d490e4b 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui/abi/abi-sysv64-arg-passing.rs b/tests/ui/abi/abi-sysv64-arg-passing.rs index 04942e984a813..c18752418a1d6 100644 --- a/tests/ui/abi/abi-sysv64-arg-passing.rs +++ b/tests/ui/abi/abi-sysv64-arg-passing.rs @@ -29,7 +29,8 @@ //@ ignore-aarch64 //@ ignore-windows -// note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows +// Windows is ignored because bootstrap doesn't yet know to compile rust_test_helpers with +// the sysv64 ABI on Windows. #[allow(dead_code)] #[allow(improper_ctypes)] diff --git a/tests/ui/abi/large-byval-align.rs b/tests/ui/abi/large-byval-align.rs index e39170df72b49..ddd579f264e67 100644 --- a/tests/ui/abi/large-byval-align.rs +++ b/tests/ui/abi/large-byval-align.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Copt-level=0 //@ only-x86_64 -//@ ignore-windows //@ min-llvm-version: 19 //@ build-pass diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index 3ab5a500dfdbb..131a10ea03b1e 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -1,4 +1,4 @@ -//@ ignore-windows +//@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows //@ aux-build:cfg-target-thread-local.rs #![feature(thread_local)] diff --git a/tests/ui/inference/issue-71584.rs b/tests/ui/inference/issue-71584.rs index 7e4d45ec4a042..61568e5467c57 100644 --- a/tests/ui/inference/issue-71584.rs +++ b/tests/ui/inference/issue-71584.rs @@ -1,4 +1,4 @@ -//@ ignore-windows different list of satisfying impls +//@ ignore-windows FIXME: We get an extra E0283 on Windows fn main() { let n: u32 = 1; let mut d: u64 = 2; diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index a169997927ebf..df73eddd8d55e 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-windows //@ ignore-apple //@ ignore-wasm32 common linkage not implemented right now @@ -11,9 +10,11 @@ pub static TEST2: bool = true; #[linkage = "internal"] pub static TEST3: bool = true; +#[cfg(not(target_env = "msvc"))] #[linkage = "linkonce"] pub static TEST4: bool = true; +#[cfg(not(target_env = "msvc"))] #[linkage = "linkonce_odr"] pub static TEST5: bool = true; diff --git a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs index 56a9358cce3cf..8c194ec50df4b 100644 --- a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs +++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs @@ -3,7 +3,6 @@ // functions. Failure results in a linker error. //@ ignore-emscripten no weak symbol support -//@ ignore-windows no extern_weak linkage //@ ignore-apple no extern_weak linkage //@ aux-build:lib.rs diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs index 5377d5eeae2bc..bb8c29694b52a 100644 --- a/tests/ui/logging-only-prints-once.rs +++ b/tests/ui/logging-only-prints-once.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-windows //@ needs-threads use std::cell::Cell; diff --git a/tests/ui/lto/weak-works.rs b/tests/ui/lto/weak-works.rs index 00e10b97d60cb..1ff47ca602d24 100644 --- a/tests/ui/lto/weak-works.rs +++ b/tests/ui/lto/weak-works.rs @@ -1,7 +1,8 @@ //@ run-pass //@ compile-flags: -C codegen-units=8 -Z thinlto -//@ ignore-windows +//@ ignore-i686-pc-windows-gnu +//@ ignore-x86_64-pc-windows-gnu #![feature(linkage)] diff --git a/tests/ui/parser/mod_file_not_exist.rs b/tests/ui/parser/mod_file_not_exist.rs index e7727944147e4..49ce44982ab98 100644 --- a/tests/ui/parser/mod_file_not_exist.rs +++ b/tests/ui/parser/mod_file_not_exist.rs @@ -1,5 +1,3 @@ -//@ ignore-windows - mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` //~^ HELP to create the module `not_a_real_file`, create file diff --git a/tests/ui/parser/mod_file_not_exist.stderr b/tests/ui/parser/mod_file_not_exist.stderr index 40041b11c8b82..d9e4e8f31f5fe 100644 --- a/tests/ui/parser/mod_file_not_exist.stderr +++ b/tests/ui/parser/mod_file_not_exist.stderr @@ -1,5 +1,5 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist.rs:3:1 + --> $DIR/mod_file_not_exist.rs:1:1 | LL | mod not_a_real_file; | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | mod not_a_real_file; = note: if there is a `mod not_a_real_file` elsewhere in the crate already, import it with `use crate::...` instead error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` - --> $DIR/mod_file_not_exist.rs:7:16 + --> $DIR/mod_file_not_exist.rs:5:16 | LL | assert_eq!(mod_file_aux::bar(), 10); | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux` diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index dd437fc0c0b8b..a957477897d54 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,6 +1,5 @@ // The specific errors produced depend the thread-local implementation. // Run only on platforms with "fast" TLS. -//@ ignore-windows FIXME(#84933) //@ ignore-wasm globals are used instead of thread locals //@ ignore-emscripten globals are used instead of thread locals //@ ignore-android does not use #[thread_local] diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index e0b6bb872b55d..1fdbf3b0c79af 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:28:44 + --> $DIR/missing-lifetime-specifier.rs:27:44 | LL | static a: RefCell>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,7 +11,7 @@ LL | static a: RefCell>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:44 + --> $DIR/missing-lifetime-specifier.rs:31:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -25,7 +25,7 @@ LL | static b: RefCell>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:47 + --> $DIR/missing-lifetime-specifier.rs:35:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -37,7 +37,7 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:40:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -51,7 +51,7 @@ LL | static d: RefCell $DIR/missing-lifetime-specifier.rs:49:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -63,7 +63,7 @@ LL | static f: RefCell>>>> = | +++++++ error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:45:44 + --> $DIR/missing-lifetime-specifier.rs:44:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -71,7 +71,7 @@ LL | static e: RefCell>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:21:11 + --> $DIR/missing-lifetime-specifier.rs:20:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -81,7 +81,7 @@ LL | static e: RefCell>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:49:45 + --> $DIR/missing-lifetime-specifier.rs:48:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -89,7 +89,7 @@ LL | static f: RefCell>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:25:7 + --> $DIR/missing-lifetime-specifier.rs:24:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs index 90a81c1e53bcb..3b7107e2dbfa6 100644 --- a/tests/ui/threads-sendsync/spawning-with-debug.rs +++ b/tests/ui/threads-sendsync/spawning-with-debug.rs @@ -1,7 +1,6 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-windows //@ exec-env:RUST_LOG=debug //@ needs-threads diff --git a/tests/ui/threads-sendsync/thread-local-extern-static.rs b/tests/ui/threads-sendsync/thread-local-extern-static.rs index ca66f8ad1d36a..ce2a221ec2e41 100644 --- a/tests/ui/threads-sendsync/thread-local-extern-static.rs +++ b/tests/ui/threads-sendsync/thread-local-extern-static.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-windows +//@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows //@ aux-build:thread-local-extern-static.rs #![feature(cfg_target_thread_local, thread_local)] diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs index dce25e62e468b..cf1824251c79c 100644 --- a/tests/ui/traits/issue-77982.rs +++ b/tests/ui/traits/issue-77982.rs @@ -1,5 +1,4 @@ -//@ ignore-windows different list of satisfying impls -//@ ignore-arm different list of satisfying impls +//@ ignore-windows FIXME: We get an extra E0283 on Windows use std::collections::HashMap; fn what() { diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 2b26a1b7ab15a..0f4b3c3c877c9 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:10:10 + --> $DIR/issue-77982.rs:9:10 | LL | opts.get(opt.as_ref()); | ^^^ ------------ type must be known at this point @@ -18,7 +18,7 @@ LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:10:10 + --> $DIR/issue-77982.rs:9:10 | LL | opts.get(opt.as_ref()); | ^^^ ------ type must be known at this point @@ -36,7 +36,7 @@ LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:15:59 + --> $DIR/issue-77982.rs:14:59 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); | --- ^^^^ @@ -56,13 +56,13 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into | +++++++++++++++++++++++ ~ error[E0283]: type annotations needed for `Box<_>` - --> $DIR/issue-77982.rs:38:9 + --> $DIR/issue-77982.rs:37:9 | LL | let _ = ().foo(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `(): Foo<'_, _>` found - --> $DIR/issue-77982.rs:31:1 + --> $DIR/issue-77982.rs:30:1 | LL | impl Foo<'static, u32> for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,13 +74,13 @@ LL | let _: Box = ().foo(); | ++++++++ error[E0283]: type annotations needed for `Box<_>` - --> $DIR/issue-77982.rs:42:9 + --> $DIR/issue-77982.rs:41:9 | LL | let _ = (&()).bar(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `&(): Bar<'_, _>` found - --> $DIR/issue-77982.rs:34:1 + --> $DIR/issue-77982.rs:33:1 | LL | impl<'a> Bar<'static, u32> for &'a () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/typeck/issue-43189.rs b/tests/ui/typeck/issue-43189.rs index 9c8cc70e63a6a..ee0fe15eebace 100644 --- a/tests/ui/typeck/issue-43189.rs +++ b/tests/ui/typeck/issue-43189.rs @@ -1,7 +1,6 @@ // Issue 46112: An extern crate pub re-exporting libcore was causing // paths rooted from `std` to be misrendered in the diagnostic output. -//@ ignore-windows //@ aux-build:xcrate-issue-43189-a.rs //@ aux-build:xcrate-issue-43189-b.rs diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr index 8432cbeca2a4b..3cc1ba9ddfe18 100644 --- a/tests/ui/typeck/issue-43189.stderr +++ b/tests/ui/typeck/issue-43189.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope - --> $DIR/issue-43189.rs:10:8 + --> $DIR/issue-43189.rs:9:8 | LL | ().a(); | ^ method not found in `()` diff --git a/tests/ui/typeck/issue-46112.rs b/tests/ui/typeck/issue-46112.rs index 4671ddd06c831..cc8029771d6d4 100644 --- a/tests/ui/typeck/issue-46112.rs +++ b/tests/ui/typeck/issue-46112.rs @@ -1,7 +1,6 @@ // Issue 46112: An extern crate pub re-exporting libcore was causing // paths rooted from `std` to be misrendered in the diagnostic output. -//@ ignore-windows //@ aux-build:xcrate-issue-46112-rexport-core.rs extern crate xcrate_issue_46112_rexport_core; diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr index 16beaea75db7f..9d439d10f1ed7 100644 --- a/tests/ui/typeck/issue-46112.stderr +++ b/tests/ui/typeck/issue-46112.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-46112.rs:9:21 + --> $DIR/issue-46112.rs:8:21 | LL | fn main() { test(Ok(())); } | -- ^^ expected `Option<()>`, found `()` @@ -9,7 +9,7 @@ LL | fn main() { test(Ok(())); } = note: expected enum `Option<()>` found unit type `()` help: the type constructed contains `()` due to the type of the argument passed - --> $DIR/issue-46112.rs:9:18 + --> $DIR/issue-46112.rs:8:18 | LL | fn main() { test(Ok(())); } | ^^^--^ From 88260f4ba4b0b9f86094bd1b2495c027bf959dbe Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Tue, 21 Jan 2025 18:00:04 +0100 Subject: [PATCH 15/22] bootstrap: only build `crt{begin,end}.o` when compiling to MUSL only MUSL needs those objects and trying to compile them to other targets, e.g. Windows or macOS, will produce C compilation errors check the target before shelling out to the C compiler and tweak `make_run` to skip the actual C compilation when the target is not MUSL fixes #135782 --- src/bootstrap/src/core/build_steps/compile.rs | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 4 +++- src/bootstrap/src/core/config/config.rs | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index fd9bf47234c63..ba8f2cc618d75 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -339,7 +339,7 @@ fn copy_self_contained_objects( // to using gcc from a glibc-targeting toolchain for linking. // To do that we have to distribute musl startup objects as a part of Rust toolchain // and link with them manually in the self-contained mode. - if target.contains("musl") && !target.contains("unikraft") { + if target.needs_crt_begin_end() { let srcdir = builder.musl_libdir(target).unwrap_or_else(|| { panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple) }); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index cf55fff4078ac..370673dfca153 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1295,7 +1295,9 @@ impl Step for CrtBeginEnd { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(CrtBeginEnd { target: run.target }); + if run.target.needs_crt_begin_end() { + run.builder.ensure(CrtBeginEnd { target: run.target }); + } } /// Build crtbegin.o/crtend.o for musl target. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index b5310108dbf70..40c995895434f 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -573,6 +573,10 @@ impl TargetSelection { env::var("OSTYPE").is_ok_and(|v| v.to_lowercase().contains("cygwin")) } + pub fn needs_crt_begin_end(&self) -> bool { + self.contains("musl") && !self.contains("unikraft") + } + /// Path to the file defining the custom target, if any. pub fn filepath(&self) -> Option<&Path> { self.file.as_ref().map(Path::new) From acb3bab5d945cb6a2c9a91c91599152c933dd59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= <39484203+jieyouxu@users.noreply.github.com> Date: Fri, 31 Jan 2025 14:43:49 +0800 Subject: [PATCH 16/22] bootstrap: add wrapper macros for `tracing`-gated tracing macros - Add wrapper macros for `error!`, `warn!`, `info!`, `debug!` and `trace!`, which `cfg(feature = "tracing")`-gates the underlying `tracing` macros. - This is not done for `span!` or `event!` because they can return span guards, and you can't really wrap that. - This is also not possible for `tracing::instrument` attribute proc-macro unless you use another attribute proc-macro to wrap that. --- src/bootstrap/src/bin/main.rs | 12 ++--- src/bootstrap/src/lib.rs | 87 +++++++++++++++--------------- src/bootstrap/src/utils/mod.rs | 2 + src/bootstrap/src/utils/tracing.rs | 49 +++++++++++++++++ 4 files changed, 99 insertions(+), 51 deletions(-) create mode 100644 src/bootstrap/src/utils/tracing.rs diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 5fcf7eda8df79..441674936c666 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -11,12 +11,12 @@ use std::str::FromStr; use std::{env, process}; use bootstrap::{ - Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, find_recent_config_change_ids, + Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids, human_readable_changes, t, }; use build_helper::ci::CiEnv; #[cfg(feature = "tracing")] -use tracing::{debug, instrument}; +use tracing::instrument; #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))] fn main() { @@ -29,10 +29,8 @@ fn main() { return; } - #[cfg(feature = "tracing")] debug!("parsing flags"); let flags = Flags::parse(&args); - #[cfg(feature = "tracing")] debug!("parsing config based on flags"); let config = Config::parse(flags); @@ -95,7 +93,6 @@ fn main() { let dump_bootstrap_shims = config.dump_bootstrap_shims; let out_dir = config.out.clone(); - #[cfg(feature = "tracing")] debug!("creating new build based on config"); Build::new(config).build(); @@ -207,8 +204,9 @@ fn check_version(config: &Config) -> Option { // Due to the conditional compilation via the `tracing` cargo feature, this means that `tracing` // usages in bootstrap need to be also gated behind the `tracing` feature: // -// - `tracing` macros (like `trace!`) and anything from `tracing`, `tracing_subscriber` and -// `tracing-tree` will need to be gated by `#[cfg(feature = "tracing")]`. +// - `tracing` macros with log levels (`trace!`, `debug!`, `warn!`, `info`, `error`) should not be +// used *directly*. You should use the wrapped `tracing` macros which gate the actual invocations +// behind `feature = "tracing"`. // - `tracing`'s `#[instrument(..)]` macro will need to be gated like `#![cfg_attr(feature = // "tracing", instrument(..))]`. #[cfg(feature = "tracing")] diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index d56f35f866cb8..2dd83d5938e9d 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -28,8 +28,6 @@ use std::{env, fs, io, str}; use build_helper::ci::gha; use build_helper::exit; use termcolor::{ColorChoice, StandardStream, WriteColor}; -#[cfg(feature = "tracing")] -use tracing::{debug, instrument, span, trace}; use utils::build_stamp::BuildStamp; use utils::channel::GitInfo; @@ -46,6 +44,8 @@ pub use core::builder::PathSet; pub use core::config::Config; pub use core::config::flags::{Flags, Subcommand}; +#[cfg(feature = "tracing")] +use tracing::{instrument, span}; pub use utils::change_tracker::{ CONFIG_CHANGE_HISTORY, find_recent_config_change_ids, human_readable_changes, }; @@ -541,72 +541,71 @@ impl Build { /// Executes the entire build, as configured by the flags and configuration. #[cfg_attr(feature = "tracing", instrument(level = "debug", name = "Build::build", skip_all))] pub fn build(&mut self) { - #[cfg(feature = "tracing")] trace!("setting up job management"); unsafe { crate::utils::job::setup(self); } - #[cfg(feature = "tracing")] - trace!("downloading rustfmt early"); - // Download rustfmt early so that it can be used in rust-analyzer configs. + trace!("downloading rustfmt early"); let _ = &builder::Builder::new(self).initial_rustfmt(); - #[cfg(feature = "tracing")] - let hardcoded_span = - span!(tracing::Level::DEBUG, "handling hardcoded subcommands (Format, Suggest, Perf)") - .entered(); - - // hardcoded subcommands - match &self.config.cmd { - Subcommand::Format { check, all } => { - return core::build_steps::format::format( - &builder::Builder::new(self), - *check, - *all, - &self.config.paths, - ); - } - Subcommand::Suggest { run } => { - return core::build_steps::suggest::suggest(&builder::Builder::new(self), *run); - } - Subcommand::Perf { .. } => { - return core::build_steps::perf::perf(&builder::Builder::new(self)); - } - _cmd => { - #[cfg(feature = "tracing")] - debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling"); + // Handle hard-coded subcommands. + { + #[cfg(feature = "tracing")] + let _hardcoded_span = span!( + tracing::Level::DEBUG, + "handling hardcoded subcommands (Format, Suggest, Perf)" + ) + .entered(); + + match &self.config.cmd { + Subcommand::Format { check, all } => { + return core::build_steps::format::format( + &builder::Builder::new(self), + *check, + *all, + &self.config.paths, + ); + } + Subcommand::Suggest { run } => { + return core::build_steps::suggest::suggest(&builder::Builder::new(self), *run); + } + Subcommand::Perf { .. } => { + return core::build_steps::perf::perf(&builder::Builder::new(self)); + } + _cmd => { + debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling"); + } } - } - #[cfg(feature = "tracing")] - drop(hardcoded_span); - #[cfg(feature = "tracing")] - debug!("handling subcommand normally"); + debug!("handling subcommand normally"); + } if !self.config.dry_run() { #[cfg(feature = "tracing")] let _real_run_span = span!(tracing::Level::DEBUG, "executing real run").entered(); + // We first do a dry-run. This is a sanity-check to ensure that + // steps don't do anything expensive in the dry-run. { #[cfg(feature = "tracing")] let _sanity_check_span = span!(tracing::Level::DEBUG, "(1) executing dry-run sanity-check").entered(); - - // We first do a dry-run. This is a sanity-check to ensure that - // steps don't do anything expensive in the dry-run. self.config.dry_run = DryRun::SelfCheck; let builder = builder::Builder::new(self); builder.execute_cli(); } - #[cfg(feature = "tracing")] - let _actual_run_span = - span!(tracing::Level::DEBUG, "(2) executing actual run").entered(); - self.config.dry_run = DryRun::Disabled; - let builder = builder::Builder::new(self); - builder.execute_cli(); + // Actual run. + { + #[cfg(feature = "tracing")] + let _actual_run_span = + span!(tracing::Level::DEBUG, "(2) executing actual run").entered(); + self.config.dry_run = DryRun::Disabled; + let builder = builder::Builder::new(self); + builder.execute_cli(); + } } else { #[cfg(feature = "tracing")] let _dry_run_span = span!(tracing::Level::DEBUG, "executing dry run").entered(); diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs index ea56932b40437..caef8ce3088a7 100644 --- a/src/bootstrap/src/utils/mod.rs +++ b/src/bootstrap/src/utils/mod.rs @@ -14,6 +14,8 @@ pub(crate) mod render_tests; pub(crate) mod shared_helpers; pub(crate) mod tarball; +pub(crate) mod tracing; + #[cfg(feature = "build-metrics")] pub(crate) mod metrics; diff --git a/src/bootstrap/src/utils/tracing.rs b/src/bootstrap/src/utils/tracing.rs new file mode 100644 index 0000000000000..9cd3b6165be61 --- /dev/null +++ b/src/bootstrap/src/utils/tracing.rs @@ -0,0 +1,49 @@ +//! Wrapper macros for [`tracing`] macros to avoid having to write `cfg(feature = "tracing")`-gated +//! `debug!`/`trace!` everytime, e.g. +//! +//! ```rust,ignore (example) +//! #[cfg(feature = "tracing")] +//! trace!("..."); +//! ``` +//! +//! When `feature = "tracing"` is inactive, these macros expand to nothing. + +#[macro_export] +macro_rules! trace { + ($($tokens:tt)*) => { + #[cfg(feature = "tracing")] + ::tracing::trace!($($tokens)*) + } +} + +#[macro_export] +macro_rules! debug { + ($($tokens:tt)*) => { + #[cfg(feature = "tracing")] + ::tracing::debug!($($tokens)*) + } +} + +#[macro_export] +macro_rules! warn { + ($($tokens:tt)*) => { + #[cfg(feature = "tracing")] + ::tracing::warn!($($tokens)*) + } +} + +#[macro_export] +macro_rules! info { + ($($tokens:tt)*) => { + #[cfg(feature = "tracing")] + ::tracing::info!($($tokens)*) + } +} + +#[macro_export] +macro_rules! error { + ($($tokens:tt)*) => { + #[cfg(feature = "tracing")] + ::tracing::error!($($tokens)*) + } +} From cc7e3a6228e3016c069b7f62ed40004ede6fafb8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:54:18 +0000 Subject: [PATCH 17/22] Remove stabilized feature gate --- library/std/tests/floats/lib.rs | 2 +- library/std/tests/sync/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs index 79813871ed940..ad82f1a44e711 100644 --- a/library/std/tests/floats/lib.rs +++ b/library/std/tests/floats/lib.rs @@ -1,4 +1,4 @@ -#![feature(f16, f128, float_gamma, float_next_up_down, float_minimum_maximum)] +#![feature(f16, f128, float_gamma, float_minimum_maximum)] use std::fmt; use std::ops::{Add, Div, Mul, Rem, Sub}; diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs index 6bf320d52f21a..51190f0894fb7 100644 --- a/library/std/tests/sync/lib.rs +++ b/library/std/tests/sync/lib.rs @@ -2,7 +2,6 @@ #![feature(mapped_lock_guards)] #![feature(mpmc_channel)] #![feature(once_cell_try)] -#![feature(once_wait)] #![feature(lock_value_accessors)] #![feature(reentrant_lock)] #![feature(rwlock_downgrade)] From 5465770ff61e02717e90fe5b02bb4737a1669197 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Jan 2025 09:20:53 +0000 Subject: [PATCH 18/22] Pretty print pattern type values with `transmute` if they don't satisfy their pattern --- compiler/rustc_const_eval/src/lib.rs | 2 + .../src/util/check_validity_requirement.rs | 52 ++++++++++++++----- compiler/rustc_const_eval/src/util/mod.rs | 1 + compiler/rustc_middle/src/hooks/mod.rs | 4 ++ compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../pattern_types.main.PreCodegen.after.mir | 2 +- tests/mir-opt/pattern_types.rs | 2 +- 7 files changed, 50 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index ecf9745b77945..8f33e0806cbce 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -57,6 +57,8 @@ pub fn provide(providers: &mut Providers) { providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) }; + providers.hooks.validate_scalar_in_layout = + |tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout); } /// `rustc_driver::main` installs a handler that will set this to `true` if diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index a729d9325c84a..83d45b12cd746 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -1,9 +1,10 @@ use rustc_abi::{BackendRepr, FieldsShape, Scalar, Variants}; -use rustc_middle::bug; +use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ HasTyCtxt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement, }; -use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt}; +use rustc_middle::ty::{PseudoCanonicalInput, ScalarInt, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug, ty}; use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::interpret::{InterpCx, MemoryKind}; @@ -34,7 +35,7 @@ pub fn check_validity_requirement<'tcx>( let layout_cx = LayoutCx::new(tcx, input.typing_env); if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks { - check_validity_requirement_strict(layout, &layout_cx, kind) + Ok(check_validity_requirement_strict(layout, &layout_cx, kind)) } else { check_validity_requirement_lax(layout, &layout_cx, kind) } @@ -46,7 +47,7 @@ fn check_validity_requirement_strict<'tcx>( ty: TyAndLayout<'tcx>, cx: &LayoutCx<'tcx>, kind: ValidityRequirement, -) -> Result> { +) -> bool { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine); @@ -69,14 +70,13 @@ fn check_validity_requirement_strict<'tcx>( // due to this. // The value we are validating is temporary and discarded at the end of this function, so // there is no point in reseting provenance and padding. - Ok(cx - .validate_operand( - &allocated.into(), - /*recursive*/ false, - /*reset_provenance_and_padding*/ false, - ) - .discard_err() - .is_some()) + cx.validate_operand( + &allocated.into(), + /*recursive*/ false, + /*reset_provenance_and_padding*/ false, + ) + .discard_err() + .is_some() } /// Implements the 'lax' (default) version of the [`check_validity_requirement`] checks; see that @@ -168,3 +168,31 @@ fn check_validity_requirement_lax<'tcx>( Ok(true) } + +pub(crate) fn validate_scalar_in_layout<'tcx>( + tcx: TyCtxtAt<'tcx>, + scalar: ScalarInt, + ty: Ty<'tcx>, +) -> bool { + let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); + + let typing_env = ty::TypingEnv::fully_monomorphized(); + let mut cx = InterpCx::new(tcx.tcx, tcx.span, typing_env, machine); + + let Ok(layout) = cx.layout_of(ty) else { + span_bug!(tcx.span, "could not compute layout of {scalar:?}:{ty:?}") + }; + let allocated = cx + .allocate(layout, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) + .expect("OOM: failed to allocate for uninit check"); + + cx.write_scalar(scalar, &allocated).unwrap(); + + cx.validate_operand( + &allocated.into(), + /*recursive*/ false, + /*reset_provenance_and_padding*/ false, + ) + .discard_err() + .is_some() +} diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index 25a9dbb2c1117..5be5ee8d1ae97 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -8,6 +8,7 @@ mod type_name; pub use self::alignment::{is_disaligned, is_within_packed}; pub use self::check_validity_requirement::check_validity_requirement; +pub(crate) use self::check_validity_requirement::validate_scalar_in_layout; pub use self::compare_types::{relate_types, sub_types}; pub use self::type_name::type_name; diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index 2be242364c111..9822eb23a2367 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -112,6 +112,10 @@ declare_hooks! { hook save_dep_graph() -> (); hook query_key_hash_verify_all() -> (); + + /// Ensure the given scalar is valid for the given type. + /// This checks non-recursive runtime validity. + hook validate_scalar_in_layout(scalar: crate::ty::ScalarInt, ty: Ty<'tcx>) -> bool; } #[cold] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6c8591dae895b..f603add3c1153 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1741,7 +1741,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { " as ", )?; } - ty::Pat(base_ty, pat) => { + ty::Pat(base_ty, pat) if self.tcx().validate_scalar_in_layout(int, ty) => { self.pretty_print_const_scalar_int(int, *base_ty, print_ty)?; p!(write(" is {pat:?}")); } diff --git a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir index 8c99902f9b8f0..5ff90de961506 100644 --- a/tests/mir-opt/pattern_types.main.PreCodegen.after.mir +++ b/tests/mir-opt/pattern_types.main.PreCodegen.after.mir @@ -5,7 +5,7 @@ fn main() -> () { scope 1 { debug x => const 2_u32 is 1..=; scope 2 { - debug y => const 0_u32 is 1..=; + debug y => const {transmute(0x00000000): (u32) is 1..=}; } } diff --git a/tests/mir-opt/pattern_types.rs b/tests/mir-opt/pattern_types.rs index 217c64b90cbbc..0369ccf9a9d56 100644 --- a/tests/mir-opt/pattern_types.rs +++ b/tests/mir-opt/pattern_types.rs @@ -7,6 +7,6 @@ use std::pat::pattern_type; fn main() { // CHECK: debug x => const 2_u32 is 1..= let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(2) }; - // CHECK: debug y => const 0_u32 is 1..= + // CHECK: debug y => const {transmute(0x00000000): (u32) is 1..=} let y: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; } From f62d1ed541d151142f580928f46d995f373bfa0f Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 18 Jan 2025 18:19:42 +0100 Subject: [PATCH 19/22] Support raw-dylib link kind on ELF raw-dylib is a link kind that allows rustc to link against a library without having any library files present. This currently only exists on Windows. rustc will take all the symbols from raw-dylib link blocks and put them in an import library, where they can then be resolved by the linker. While import libraries don't exist on ELF, it would still be convenient to have this same functionality. Not having the libraries present at build-time can be convenient for several reasons, especially cross-compilation. With raw-dylib, code linking against a library can be cross-compiled without needing to have these libraries available on the build machine. If the libc crate makes use of this, it would allow cross-compilation without having any libc available on the build machine. This is not yet possible with this implementation, at least against libc's like glibc that use symbol versioning. The raw-dylib kind could be extended with support for symbol versioning in the future. This implementation is very experimental and I have not tested it very well. I have tested it for a toy example and the lz4-sys crate, where it was able to successfully link a binary despite not having a corresponding library at build-time. --- compiler/rustc_codegen_ssa/src/back/link.rs | 212 ++++------ .../src/back/link/raw_dylib.rs | 372 ++++++++++++++++++ .../rustc_codegen_ssa/src/back/metadata.rs | 96 ++--- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_metadata/messages.ftl | 3 + compiler/rustc_metadata/src/native_libs.rs | 21 +- compiler/rustc_session/src/utils.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 68 +++- .../rustc-dev-guide/src/tests/directives.md | 1 + src/tools/compiletest/src/directive-list.rs | 2 + src/tools/compiletest/src/header/cfg.rs | 9 + tests/run-make/linker-warning/rmake.rs | 2 + tests/run-make/linker-warning/short-error.txt | 2 +- .../raw-dylib-elf-verbatim-absolute/main.rs | 11 + .../output.txt | 1 + .../raw-dylib-elf-verbatim-absolute/rmake.rs | 15 + .../run-make/raw-dylib-elf-verbatim/library.c | 3 + tests/run-make/raw-dylib-elf-verbatim/main.rs | 11 + .../raw-dylib-elf-verbatim/output.txt | 1 + .../run-make/raw-dylib-elf-verbatim/rmake.rs | 26 ++ tests/run-make/raw-dylib-elf/library.c | 3 + tests/run-make/raw-dylib-elf/main.rs | 11 + tests/run-make/raw-dylib-elf/output.txt | 1 + tests/run-make/raw-dylib-elf/rmake.rs | 24 ++ tests/run-make/reproducible-build/linker.rs | 2 + .../feature-gate-raw-dylib-elf.rs | 8 + .../feature-gate-raw-dylib-elf.stderr | 13 + .../raw-dylib/elf/multiple-libraries.rs | 33 ++ .../raw-dylib/elf/single-symbol.rs | 25 ++ .../ui/linkage-attr/raw-dylib/elf/verbatim.rs | 25 ++ .../raw-dylib/windows}/dlltool-failed.rs | 0 .../raw-dylib/windows}/dlltool-failed.stderr | 0 .../import-name-type-invalid-format.rs | 0 .../import-name-type-invalid-format.stderr | 0 .../windows}/import-name-type-multiple.rs | 0 .../windows}/import-name-type-multiple.stderr | 0 .../import-name-type-unknown-value.rs | 0 .../import-name-type-unknown-value.stderr | 0 .../import-name-type-unsupported-link-kind.rs | 0 ...ort-name-type-unsupported-link-kind.stderr | 0 .../windows}/import-name-type-x86-only.rs | 0 .../windows}/import-name-type-x86-only.stderr | 0 .../raw-dylib/windows}/invalid-dlltool.rs | 0 .../raw-dylib/windows}/invalid-dlltool.stderr | 0 .../windows}/link-ordinal-and-name.rs | 0 .../windows}/link-ordinal-and-name.stderr | 0 .../windows}/link-ordinal-invalid-format.rs | 0 .../link-ordinal-invalid-format.stderr | 0 .../windows}/link-ordinal-missing-argument.rs | 0 .../link-ordinal-missing-argument.stderr | 0 .../windows}/link-ordinal-multiple.rs | 0 .../windows}/link-ordinal-multiple.stderr | 0 .../windows}/link-ordinal-not-foreign-fn.rs | 0 .../link-ordinal-not-foreign-fn.stderr | 0 .../windows}/link-ordinal-too-large.rs | 0 .../windows}/link-ordinal-too-large.stderr | 0 .../link-ordinal-too-many-arguments.rs | 0 .../link-ordinal-too-many-arguments.stderr | 0 .../link-ordinal-unsupported-link-kind.rs | 0 .../link-ordinal-unsupported-link-kind.stderr | 0 .../windows}/multiple-declarations.rs | 0 .../windows}/multiple-declarations.stderr | 0 .../windows/raw-dylib-windows-only.elf.stderr | 13 + .../windows/raw-dylib-windows-only.rs | 9 + .../raw-dylib/windows}/unsupported-abi.rs | 0 .../raw-dylib/windows}/unsupported-abi.stderr | 0 .../raw-dylib-windows-only.rs | 5 - .../raw-dylib-windows-only.stderr | 9 - 69 files changed, 820 insertions(+), 221 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt create mode 100644 tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim/library.c create mode 100644 tests/run-make/raw-dylib-elf-verbatim/main.rs create mode 100644 tests/run-make/raw-dylib-elf-verbatim/output.txt create mode 100644 tests/run-make/raw-dylib-elf-verbatim/rmake.rs create mode 100644 tests/run-make/raw-dylib-elf/library.c create mode 100644 tests/run-make/raw-dylib-elf/main.rs create mode 100644 tests/run-make/raw-dylib-elf/output.txt create mode 100644 tests/run-make/raw-dylib-elf/rmake.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs create mode 100644 tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs create mode 100644 tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/dlltool-failed.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/dlltool-failed.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-invalid-format.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-invalid-format.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-multiple.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-multiple.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unknown-value.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unknown-value.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unsupported-link-kind.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-unsupported-link-kind.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-x86-only.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/import-name-type-x86-only.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/invalid-dlltool.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/invalid-dlltool.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-and-name.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-and-name.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-invalid-format.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-invalid-format.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-missing-argument.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-missing-argument.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-multiple.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-multiple.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-not-foreign-fn.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-not-foreign-fn.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-large.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-large.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-many-arguments.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-too-many-arguments.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-unsupported-link-kind.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/link-ordinal-unsupported-link-kind.stderr (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/multiple-declarations.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/multiple-declarations.stderr (100%) create mode 100644 tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr create mode 100644 tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/unsupported-abi.rs (100%) rename tests/ui/{rfcs/rfc-2627-raw-dylib => linkage-attr/raw-dylib/windows}/unsupported-abi.stderr (100%) delete mode 100644 tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs delete mode 100644 tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0d1..cc95431ccb5bd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,3 +1,5 @@ +mod raw_dylib; + use std::collections::BTreeSet; use std::ffi::OsString; use std::fs::{File, OpenOptions, read}; @@ -12,7 +14,7 @@ use itertools::Itertools; use regex::Regex; use rustc_arena::TypedArena; use rustc_ast::CRATE_NODE_ID; -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; @@ -30,7 +32,6 @@ use rustc_session::config::{ self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames, OutputType, PrintKind, SplitDwarfKind, Strip, }; -use rustc_session::cstore::DllImport; use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; @@ -48,15 +49,14 @@ use rustc_target::spec::{ use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ImportLibraryItem}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; use super::{apple, versioned_llvm_target}; use crate::{ - CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, - looks_like_rust_object_file, + CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -381,16 +381,22 @@ fn link_rlib<'a>( } } - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - codegen_results.crate_info.used_libraries.iter(), - tmpdir.as_ref(), - true, - ) { - ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { - sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); - }); + // On Windows, we add the raw-dylib import libraries to the rlibs already. + // But on ELF, this is not possible, as a shared object cannot be a member of a static library. + // Instead, we add all raw-dylibs to the final link on ELF. + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + codegen_results.crate_info.used_libraries.iter(), + tmpdir.as_ref(), + true, + ) { + ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| { + sess.dcx() + .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); + }); + } } if let Some(trailing_metadata) = trailing_metadata { @@ -431,108 +437,6 @@ fn link_rlib<'a>( ab } -/// Extract all symbols defined in raw-dylib libraries, collated by library name. -/// -/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, -/// then the CodegenResults value contains one NativeLib instance for each block. However, the -/// linker appears to expect only a single import library for each library used, so we need to -/// collate the symbols together by library name before generating the import libraries. -fn collate_raw_dylibs<'a>( - sess: &Session, - used_libraries: impl IntoIterator, -) -> Vec<(String, Vec)> { - // Use index maps to preserve original order of imports and libraries. - let mut dylib_table = FxIndexMap::>::default(); - - for lib in used_libraries { - if lib.kind == NativeLibKind::RawDylib { - let ext = if lib.verbatim { "" } else { ".dll" }; - let name = format!("{}{}", lib.name, ext); - let imports = dylib_table.entry(name.clone()).or_default(); - for import in &lib.dll_imports { - if let Some(old_import) = imports.insert(import.name, import) { - // FIXME: when we add support for ordinals, figure out if we need to do anything - // if we have two DllImport values with the same name but different ordinals. - if import.calling_convention != old_import.calling_convention { - sess.dcx().emit_err(errors::MultipleExternalFuncDecl { - span: import.span, - function: import.name, - library_name: &name, - }); - } - } - } - } - } - sess.dcx().abort_if_errors(); - dylib_table - .into_iter() - .map(|(name, imports)| { - (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) - }) - .collect() -} - -fn create_dll_import_libs<'a>( - sess: &Session, - archive_builder_builder: &dyn ArchiveBuilderBuilder, - used_libraries: impl IntoIterator, - tmpdir: &Path, - is_direct_dependency: bool, -) -> Vec { - collate_raw_dylibs(sess, used_libraries) - .into_iter() - .map(|(raw_dylib_name, raw_dylib_imports)| { - let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; - let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib")); - - let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target); - - let items: Vec = raw_dylib_imports - .iter() - .map(|import: &DllImport| { - if sess.target.arch == "x86" { - ImportLibraryItem { - name: common::i686_decorated_name( - import, - mingw_gnu_toolchain, - false, - false, - ), - ordinal: import.ordinal(), - symbol_name: import.is_missing_decorations().then(|| { - common::i686_decorated_name( - import, - mingw_gnu_toolchain, - false, - true, - ) - }), - is_data: !import.is_fn, - } - } else { - ImportLibraryItem { - name: import.name.to_string(), - ordinal: import.ordinal(), - symbol_name: None, - is_data: !import.is_fn, - } - } - }) - .collect(); - - archive_builder_builder.create_dll_import_lib( - sess, - &raw_dylib_name, - items, - &output_path, - ); - - output_path - }) - .collect() -} - /// Create a static archive. /// /// This is essentially the same thing as an rlib, but it also involves adding all of the upstream @@ -2370,15 +2274,39 @@ fn linker_with_args( link_output_kind, ); + // Raw-dylibs from all crates. + let raw_dylib_dir = tmpdir.join("raw-dylibs"); + if sess.target.binary_format() == object::BinaryFormat::Elf { + // On ELF we can't pass the raw-dylibs stubs to the linker as a path, + // instead we need to pass them via -l. To find the stub, we need to add + // the directory of the stub to the linker search path. + // We make an extra directory for this to avoid polluting the search path. + if let Err(error) = fs::create_dir(&raw_dylib_dir) { + sess.dcx().emit_fatal(errors::CreateTempDir { error }) + } + cmd.include_path(&raw_dylib_dir); + } + // Link with the import library generated for any raw-dylib functions. - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - codegen_results.crate_info.used_libraries.iter(), - tmpdir, - true, - ) { - cmd.add_object(&output_path); + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + codegen_results.crate_info.used_libraries.iter(), + tmpdir, + true, + ) { + cmd.add_object(&output_path); + } + } else { + for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects( + sess, + codegen_results.crate_info.used_libraries.iter(), + &raw_dylib_dir, + ) { + // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects. + cmd.link_dylib_by_name(&link_path, true, false); + } } // As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case // they are used within inlined functions or instantiated generic functions. We do this *after* @@ -2397,19 +2325,35 @@ fn linker_with_args( .native_libraries .iter() .filter_map(|(&cnum, libraries)| { - (dependency_linkage[cnum] != Linkage::Static).then_some(libraries) + if sess.target.is_like_windows { + (dependency_linkage[cnum] != Linkage::Static).then_some(libraries) + } else { + Some(libraries) + } }) .flatten() .collect::>(); native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str())); - for output_path in create_dll_import_libs( - sess, - archive_builder_builder, - native_libraries_from_nonstatics, - tmpdir, - false, - ) { - cmd.add_object(&output_path); + + if sess.target.is_like_windows { + for output_path in raw_dylib::create_raw_dylib_dll_import_libs( + sess, + archive_builder_builder, + native_libraries_from_nonstatics, + tmpdir, + false, + ) { + cmd.add_object(&output_path); + } + } else { + for link_path in raw_dylib::create_raw_dylib_elf_stub_shared_objects( + sess, + native_libraries_from_nonstatics, + &raw_dylib_dir, + ) { + // Always use verbatim linkage, see comments in create_raw_dylib_elf_stub_shared_objects. + cmd.link_dylib_by_name(&link_path, true, false); + } } // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs new file mode 100644 index 0000000000000..4bc8fec6fb5da --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs @@ -0,0 +1,372 @@ +use std::fs; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; + +use rustc_abi::Endian; +use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; +use rustc_session::Session; +use rustc_session::cstore::DllImport; +use rustc_session::utils::NativeLibKind; +use rustc_span::Symbol; + +use crate::back::archive::ImportLibraryItem; +use crate::back::link::ArchiveBuilderBuilder; +use crate::errors::ErrorCreatingImportLibrary; +use crate::{NativeLib, common, errors}; + +/// Extract all symbols defined in raw-dylib libraries, collated by library name. +/// +/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, +/// then the CodegenResults value contains one NativeLib instance for each block. However, the +/// linker appears to expect only a single import library for each library used, so we need to +/// collate the symbols together by library name before generating the import libraries. +fn collate_raw_dylibs_windows<'a>( + sess: &Session, + used_libraries: impl IntoIterator, +) -> Vec<(String, Vec)> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); + + for lib in used_libraries { + if lib.kind == NativeLibKind::RawDylib { + let ext = if lib.verbatim { "" } else { ".dll" }; + let name = format!("{}{}", lib.name, ext); + let imports = dylib_table.entry(name.clone()).or_default(); + for import in &lib.dll_imports { + if let Some(old_import) = imports.insert(import.name, import) { + // FIXME: when we add support for ordinals, figure out if we need to do anything + // if we have two DllImport values with the same name but different ordinals. + if import.calling_convention != old_import.calling_convention { + sess.dcx().emit_err(errors::MultipleExternalFuncDecl { + span: import.span, + function: import.name, + library_name: &name, + }); + } + } + } + } + } + sess.dcx().abort_if_errors(); + dylib_table + .into_iter() + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) + }) + .collect() +} + +pub(super) fn create_raw_dylib_dll_import_libs<'a>( + sess: &Session, + archive_builder_builder: &dyn ArchiveBuilderBuilder, + used_libraries: impl IntoIterator, + tmpdir: &Path, + is_direct_dependency: bool, +) -> Vec { + collate_raw_dylibs_windows(sess, used_libraries) + .into_iter() + .map(|(raw_dylib_name, raw_dylib_imports)| { + let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; + let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib")); + + let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target); + + let items: Vec = raw_dylib_imports + .iter() + .map(|import: &DllImport| { + if sess.target.arch == "x86" { + ImportLibraryItem { + name: common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + false, + ), + ordinal: import.ordinal(), + symbol_name: import.is_missing_decorations().then(|| { + common::i686_decorated_name( + import, + mingw_gnu_toolchain, + false, + true, + ) + }), + is_data: !import.is_fn, + } + } else { + ImportLibraryItem { + name: import.name.to_string(), + ordinal: import.ordinal(), + symbol_name: None, + is_data: !import.is_fn, + } + } + }) + .collect(); + + archive_builder_builder.create_dll_import_lib( + sess, + &raw_dylib_name, + items, + &output_path, + ); + + output_path + }) + .collect() +} + +/// Extract all symbols defined in raw-dylib libraries, collated by library name. +/// +/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library, +/// then the CodegenResults value contains one NativeLib instance for each block. However, the +/// linker appears to expect only a single import library for each library used, so we need to +/// collate the symbols together by library name before generating the import libraries. +fn collate_raw_dylibs_elf<'a>( + sess: &Session, + used_libraries: impl IntoIterator, +) -> Vec<(String, Vec)> { + // Use index maps to preserve original order of imports and libraries. + let mut dylib_table = FxIndexMap::>::default(); + + for lib in used_libraries { + if lib.kind == NativeLibKind::RawDylib { + let filename = if lib.verbatim { + lib.name.as_str().to_owned() + } else { + let ext = sess.target.dll_suffix.as_ref(); + let prefix = sess.target.dll_prefix.as_ref(); + format!("{prefix}{}{ext}", lib.name) + }; + + let imports = dylib_table.entry(filename.clone()).or_default(); + for import in &lib.dll_imports { + imports.insert(import.name, import); + } + } + } + sess.dcx().abort_if_errors(); + dylib_table + .into_iter() + .map(|(name, imports)| { + (name, imports.into_iter().map(|(_, import)| import.clone()).collect()) + }) + .collect() +} + +pub(super) fn create_raw_dylib_elf_stub_shared_objects<'a>( + sess: &Session, + used_libraries: impl IntoIterator, + raw_dylib_so_dir: &Path, +) -> Vec { + collate_raw_dylibs_elf(sess, used_libraries) + .into_iter() + .map(|(load_filename, raw_dylib_imports)| { + use std::hash::Hash; + + // `load_filename` is the *target/loader* filename that will end up in NEEDED. + // Usually this will be something like `libc.so` or `libc.so.6` but with + // verbatim it might also be an absolute path. + // To be able to support this properly, we always put this load filename + // into the SONAME of the library and link it via a temporary file with a random name. + // This also avoids naming conflicts with non-raw-dylib linkage of the same library. + + let shared_object = create_elf_raw_dylib_stub(sess, &load_filename, &raw_dylib_imports); + + let mut file_name_hasher = StableHasher::new(); + load_filename.hash(&mut file_name_hasher); + for raw_dylib in raw_dylib_imports { + raw_dylib.name.as_str().hash(&mut file_name_hasher); + } + + let library_filename: Hash128 = file_name_hasher.finish(); + let temporary_lib_name = format!( + "{}{}{}", + sess.target.dll_prefix, + library_filename.as_u128().to_base_fixed_len(CASE_INSENSITIVE), + sess.target.dll_suffix + ); + let link_path = raw_dylib_so_dir.join(&temporary_lib_name); + + let file = match fs::File::create_new(&link_path) { + Ok(file) => file, + Err(error) => sess.dcx().emit_fatal(ErrorCreatingImportLibrary { + lib_name: &load_filename, + error: error.to_string(), + }), + }; + if let Err(error) = BufWriter::new(file).write_all(&shared_object) { + sess.dcx().emit_fatal(ErrorCreatingImportLibrary { + lib_name: &load_filename, + error: error.to_string(), + }); + }; + + temporary_lib_name + }) + .collect() +} + +/// Create an ELF .so stub file for raw-dylib. +/// It exports all the provided symbols, but is otherwise empty. +fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]) -> Vec { + use object::write::elf as write; + use object::{Architecture, elf}; + + let mut stub_buf = Vec::new(); + + // Build the stub ELF using the object crate. + // The high-level portable API does not allow for the fine-grained control we need, + // so this uses the low-level object::write::elf API. + // The low-level API consists of two stages: reservation and writing. + // We first reserve space for all the things in the binary and then write them. + // It is important that the order of reservation matches the order of writing. + // The object crate contains many debug asserts that fire if you get this wrong. + + let endianness = match sess.target.options.endian { + Endian::Little => object::Endianness::Little, + Endian::Big => object::Endianness::Big, + }; + let mut stub = write::Writer::new(endianness, true, &mut stub_buf); + + // These initial reservations don't reserve any bytes in the binary yet, + // they just allocate in the internal data structures. + + // First, we crate the dynamic symbol table. It starts with a null symbol + // and then all the symbols and their dynamic strings. + stub.reserve_null_dynamic_symbol_index(); + + let dynstrs = symbols + .iter() + .map(|sym| { + stub.reserve_dynamic_symbol_index(); + (sym, stub.add_dynamic_string(sym.name.as_str().as_bytes())) + }) + .collect::>(); + + let soname = stub.add_dynamic_string(soname.as_bytes()); + + // Reserve the sections. + // We have the minimal sections for a dynamic SO and .text where we point our dummy symbols to. + stub.reserve_shstrtab_section_index(); + let text_section_name = stub.add_section_name(".text".as_bytes()); + let text_section = stub.reserve_section_index(); + stub.reserve_dynstr_section_index(); + stub.reserve_dynsym_section_index(); + stub.reserve_dynamic_section_index(); + + // These reservations now determine the actual layout order of the object file. + stub.reserve_file_header(); + stub.reserve_shstrtab(); + stub.reserve_section_headers(); + stub.reserve_dynstr(); + stub.reserve_dynsym(); + stub.reserve_dynamic(2); // DT_SONAME, DT_NULL + + // First write the ELF header with the arch information. + let Some((arch, sub_arch)) = sess.target.object_architecture(&sess.unstable_target_features) + else { + sess.dcx().fatal(format!( + "raw-dylib is not supported for the architecture `{}`", + sess.target.arch + )); + }; + let e_machine = match (arch, sub_arch) { + (Architecture::Aarch64, None) => elf::EM_AARCH64, + (Architecture::Aarch64_Ilp32, None) => elf::EM_AARCH64, + (Architecture::Arm, None) => elf::EM_ARM, + (Architecture::Avr, None) => elf::EM_AVR, + (Architecture::Bpf, None) => elf::EM_BPF, + (Architecture::Csky, None) => elf::EM_CSKY, + (Architecture::E2K32, None) => elf::EM_MCST_ELBRUS, + (Architecture::E2K64, None) => elf::EM_MCST_ELBRUS, + (Architecture::I386, None) => elf::EM_386, + (Architecture::X86_64, None) => elf::EM_X86_64, + (Architecture::X86_64_X32, None) => elf::EM_X86_64, + (Architecture::Hexagon, None) => elf::EM_HEXAGON, + (Architecture::LoongArch64, None) => elf::EM_LOONGARCH, + (Architecture::M68k, None) => elf::EM_68K, + (Architecture::Mips, None) => elf::EM_MIPS, + (Architecture::Mips64, None) => elf::EM_MIPS, + (Architecture::Mips64_N32, None) => elf::EM_MIPS, + (Architecture::Msp430, None) => elf::EM_MSP430, + (Architecture::PowerPc, None) => elf::EM_PPC, + (Architecture::PowerPc64, None) => elf::EM_PPC64, + (Architecture::Riscv32, None) => elf::EM_RISCV, + (Architecture::Riscv64, None) => elf::EM_RISCV, + (Architecture::S390x, None) => elf::EM_S390, + (Architecture::Sbf, None) => elf::EM_SBF, + (Architecture::Sharc, None) => elf::EM_SHARC, + (Architecture::Sparc, None) => elf::EM_SPARC, + (Architecture::Sparc32Plus, None) => elf::EM_SPARC32PLUS, + (Architecture::Sparc64, None) => elf::EM_SPARCV9, + (Architecture::Xtensa, None) => elf::EM_XTENSA, + _ => { + sess.dcx().fatal(format!( + "raw-dylib is not supported for the architecture `{}`", + sess.target.arch + )); + } + }; + + stub.write_file_header(&write::FileHeader { + os_abi: crate::back::metadata::elf_os_abi(sess), + abi_version: 0, + e_type: object::elf::ET_DYN, + e_machine, + e_entry: 0, + e_flags: crate::back::metadata::elf_e_flags(arch, sess), + }) + .unwrap(); + + // .shstrtab + stub.write_shstrtab(); + + // Section headers + stub.write_null_section_header(); + stub.write_shstrtab_section_header(); + // Create a dummy .text section for our dummy symbols. + stub.write_section_header(&write::SectionHeader { + name: Some(text_section_name), + sh_type: elf::SHT_PROGBITS, + sh_flags: 0, + sh_addr: 0, + sh_offset: 0, + sh_size: 0, + sh_link: 0, + sh_info: 0, + sh_addralign: 1, + sh_entsize: 0, + }); + stub.write_dynstr_section_header(0); + stub.write_dynsym_section_header(0, 1); + stub.write_dynamic_section_header(0); + + // .dynstr + stub.write_dynstr(); + + // .dynsym + stub.write_null_dynamic_symbol(); + for (_, name) in dynstrs { + stub.write_dynamic_symbol(&write::Sym { + name: Some(name), + st_info: (elf::STB_GLOBAL << 4) | elf::STT_NOTYPE, + st_other: elf::STV_DEFAULT, + section: Some(text_section), + st_shndx: 0, // ignored by object in favor of the `section` field + st_value: 0, + st_size: 0, + }); + } + + // .dynamic + // the DT_SONAME will be used by the linker to populate DT_NEEDED + // which the loader uses to find the library. + // DT_NULL terminates the .dynamic table. + stub.write_dynamic_string(elf::DT_SONAME, soname); + stub.write_dynamic(elf::DT_NULL, 0); + + stub_buf +} diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index ba7b53321a83d..40ad70057ee9f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -9,8 +9,7 @@ use itertools::Itertools; use object::write::{self, StandardSegment, Symbol, SymbolSection}; use object::{ Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol, - SectionFlags, SectionKind, SubArchitecture, SymbolFlags, SymbolKind, SymbolScope, elf, pe, - xcoff, + SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff, }; use rustc_abi::Endian; use rustc_data_structures::memmap::Mmap; @@ -206,61 +205,12 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Endianness::Little, Endian::Big => Endianness::Big, }; - let (architecture, sub_architecture) = match &sess.target.arch[..] { - "arm" => (Architecture::Arm, None), - "aarch64" => ( - if sess.target.pointer_width == 32 { - Architecture::Aarch64_Ilp32 - } else { - Architecture::Aarch64 - }, - None, - ), - "x86" => (Architecture::I386, None), - "s390x" => (Architecture::S390x, None), - "mips" | "mips32r6" => (Architecture::Mips, None), - "mips64" | "mips64r6" => (Architecture::Mips64, None), - "x86_64" => ( - if sess.target.pointer_width == 32 { - Architecture::X86_64_X32 - } else { - Architecture::X86_64 - }, - None, - ), - "powerpc" => (Architecture::PowerPc, None), - "powerpc64" => (Architecture::PowerPc64, None), - "riscv32" => (Architecture::Riscv32, None), - "riscv64" => (Architecture::Riscv64, None), - "sparc" => { - if sess.unstable_target_features.contains(&sym::v8plus) { - // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode - (Architecture::Sparc32Plus, None) - } else { - // Target uses V7 or V8, aka EM_SPARC - (Architecture::Sparc, None) - } - } - "sparc64" => (Architecture::Sparc64, None), - "avr" => (Architecture::Avr, None), - "msp430" => (Architecture::Msp430, None), - "hexagon" => (Architecture::Hexagon, None), - "bpf" => (Architecture::Bpf, None), - "loongarch64" => (Architecture::LoongArch64, None), - "csky" => (Architecture::Csky, None), - "arm64ec" => (Architecture::Aarch64, Some(SubArchitecture::Arm64EC)), - // Unsupported architecture. - _ => return None, - }; - let binary_format = if sess.target.is_like_osx { - BinaryFormat::MachO - } else if sess.target.is_like_windows { - BinaryFormat::Coff - } else if sess.target.is_like_aix { - BinaryFormat::Xcoff - } else { - BinaryFormat::Elf + let Some((architecture, sub_architecture)) = + sess.target.object_architecture(&sess.unstable_target_features) + else { + return None; }; + let binary_format = sess.target.binary_format(); let mut file = write::Object::new(binary_format, architecture, endianness); file.set_sub_architecture(sub_architecture); @@ -300,7 +250,26 @@ pub(crate) fn create_object_file(sess: &Session) -> Option u8 { + match sess.target.options.os.as_ref() { + "hermit" => elf::ELFOSABI_STANDALONE, + "freebsd" => elf::ELFOSABI_FREEBSD, + "solaris" => elf::ELFOSABI_SOLARIS, + _ => elf::ELFOSABI_NONE, + } +} + +pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 { + match architecture { Architecture::Mips => { let arch = match sess.target.options.cpu.as_ref() { "mips1" => elf::EF_MIPS_ARCH_1, @@ -391,18 +360,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option 0, - }; - // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI` - let os_abi = match sess.target.options.os.as_ref() { - "hermit" => elf::ELFOSABI_STANDALONE, - "freebsd" => elf::ELFOSABI_FREEBSD, - "solaris" => elf::ELFOSABI_SOLARIS, - _ => elf::ELFOSABI_NONE, - }; - let abi_version = 0; - add_gnu_property_note(&mut file, architecture, binary_format, endianness); - file.flags = FileFlags::Elf { os_abi, abi_version, e_flags }; - Some(file) + } } /// Mach-O files contain information about: diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1a216ebf117c6..b6a28af048036 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -592,6 +592,8 @@ declare_features! ( (unstable, precise_capturing_in_traits, "1.83.0", Some(130044)), /// Allows macro attributes on expressions, statements and non-inline modules. (unstable, proc_macro_hygiene, "1.30.0", Some(54727)), + /// Allows the use of raw-dylibs on ELF platforms + (incomplete, raw_dylib_elf, "CURRENT_RUSTC_VERSION", Some(135694)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024—structural variant diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index d2b5ae5318592..bebbc1a8d5a8b 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -233,6 +233,9 @@ metadata_prev_alloc_error_handler = metadata_prev_global_alloc = previous global allocator defined here +metadata_raw_dylib_elf_unstable = + link kind `raw-dylib` is unstable on ELF platforms + metadata_raw_dylib_no_nul = link name must not contain NUL characters if link kind is `raw-dylib` diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 2a1e4b261e737..4be54a2a3511d 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -17,7 +17,7 @@ use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::LinkSelfContainedComponents; +use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents}; use crate::{errors, fluent_generated}; @@ -263,9 +263,26 @@ impl<'tcx> Collector<'tcx> { NativeLibKind::Framework { as_needed: None } } "raw-dylib" => { - if !sess.target.is_like_windows { + if sess.target.is_like_windows { + // raw-dylib is stable and working on Windows + } else if sess.target.binary_format() == BinaryFormat::Elf + && features.raw_dylib_elf() + { + // raw-dylib is unstable on ELF, but the user opted in + } else if sess.target.binary_format() == BinaryFormat::Elf + && sess.is_nightly_build() + { + feature_err( + sess, + sym::raw_dylib_elf, + span, + fluent_generated::metadata_raw_dylib_elf_unstable, + ) + .emit(); + } else { sess.dcx().emit_err(errors::RawDylibOnlyWindows { span }); } + NativeLibKind::RawDylib } "link-arg" => { diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index 9182789cf0269..fcede379b893a 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -34,6 +34,7 @@ pub enum NativeLibKind { as_needed: Option, }, /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library. + /// On Linux, it refers to a generated shared library stub. RawDylib, /// A macOS-specific kind of dynamic libraries. Framework { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 322da9390113d..a8a45a77f5d23 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1596,6 +1596,7 @@ symbols! { quote, range_inclusive_new, raw_dylib, + raw_dylib_elf, raw_eq, raw_identifiers, raw_ref_op, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 3fc7a07fb9139..39b5c2b1ca2e7 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -42,7 +42,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use std::{fmt, io}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_fs_util::try_canonicalize; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -69,6 +69,7 @@ mod base; mod json; pub use base::avr_gnu::ef_avr_arch; +pub use object::BinaryFormat; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -3407,6 +3408,71 @@ impl Target { s => s.clone(), } } + + pub fn binary_format(&self) -> object::BinaryFormat { + if self.is_like_osx { + object::BinaryFormat::MachO + } else if self.is_like_windows { + object::BinaryFormat::Coff + } else if self.is_like_aix { + object::BinaryFormat::Xcoff + } else { + object::BinaryFormat::Elf + } + } + + pub fn object_architecture( + &self, + unstable_target_features: &FxIndexSet, + ) -> Option<(object::Architecture, Option)> { + use object::Architecture; + Some(match self.arch.as_ref() { + "arm" => (Architecture::Arm, None), + "aarch64" => ( + if self.pointer_width == 32 { + Architecture::Aarch64_Ilp32 + } else { + Architecture::Aarch64 + }, + None, + ), + "x86" => (Architecture::I386, None), + "s390x" => (Architecture::S390x, None), + "mips" | "mips32r6" => (Architecture::Mips, None), + "mips64" | "mips64r6" => (Architecture::Mips64, None), + "x86_64" => ( + if self.pointer_width == 32 { + Architecture::X86_64_X32 + } else { + Architecture::X86_64 + }, + None, + ), + "powerpc" => (Architecture::PowerPc, None), + "powerpc64" => (Architecture::PowerPc64, None), + "riscv32" => (Architecture::Riscv32, None), + "riscv64" => (Architecture::Riscv64, None), + "sparc" => { + if unstable_target_features.contains(&sym::v8plus) { + // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode + (Architecture::Sparc32Plus, None) + } else { + // Target uses V7 or V8, aka EM_SPARC + (Architecture::Sparc, None) + } + } + "sparc64" => (Architecture::Sparc64, None), + "avr" => (Architecture::Avr, None), + "msp430" => (Architecture::Msp430, None), + "hexagon" => (Architecture::Hexagon, None), + "bpf" => (Architecture::Bpf, None), + "loongarch64" => (Architecture::LoongArch64, None), + "csky" => (Architecture::Csky, None), + "arm64ec" => (Architecture::Aarch64, Some(object::SubArchitecture::Arm64EC)), + // Unsupported architecture. + _ => return None, + }) + } } /// Either a target tuple string or a path to a JSON file. diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 9e0f8f9c279c7..15a8737729f84 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -142,6 +142,7 @@ Some examples of `X` in `ignore-X` or `only-X`: matches that target as well as the emscripten targets. - Pointer width: `32bit`, `64bit` - Endianness: `endian-big` +- Binary format: `elf` - Stage: `stage0`, `stage1`, `stage2` - Channel: `stable`, `beta` - When cross compiling: `cross-compile` diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 71496444660f5..fe831e33528bd 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -48,6 +48,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-coverage-run", "ignore-cross-compile", "ignore-eabi", + "ignore-elf", "ignore-emscripten", "ignore-endian-big", "ignore-enzyme", @@ -177,6 +178,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-bpf", "only-cdb", "only-dist", + "only-elf", "only-emscripten", "only-gnu", "only-i686-pc-windows-gnu", diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 6e5ced17c2084..d8dc6d7ca4c15 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -166,6 +166,15 @@ fn parse_cfg_name_directive<'a>( message: "when the target vendor is Apple" } + condition! { + name: "elf", + condition: !config.target.contains("windows") + && !config.target.contains("apple") + && !config.target.contains("aix") + && !config.target.contains("uefi"), + message: "when the target binary format is ELF" + } + condition! { name: "enzyme", condition: config.has_enzyme, diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 30387af428c69..73ad248b6f363 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -60,6 +60,8 @@ fn main() { regex::escape(run_make_support::build_root().to_str().unwrap()), "/build-root", ) + .normalize(r#""[^"]*\/symbols.o""#, "\"/symbols.o\"") + .normalize(r#""[^"]*\/raw-dylibs""#, "\"/raw-dylibs\"") .run(); } diff --git a/tests/run-make/linker-warning/short-error.txt b/tests/run-make/linker-warning/short-error.txt index dd3b742bbfd56..a7f48af885a05 100644 --- a/tests/run-make/linker-warning/short-error.txt +++ b/tests/run-make/linker-warning/short-error.txt @@ -1,6 +1,6 @@ error: linking with `./fake-linker` failed: exit status: 1 | - = note: "./fake-linker" "-m64" "/tmp/rustc/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" + = note: "./fake-linker" "-m64" "/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-L" "/raw-dylibs" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" = note: some arguments are omitted. use `--verbose` to show all linker arguments = note: error: baz diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs new file mode 100644 index 0000000000000..75bd7747f4fe7 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "/absolute-path/liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs new file mode 100644 index 0000000000000..53bace7b62dd8 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim-absolute/rmake.rs @@ -0,0 +1,15 @@ +//@ only-elf + +//! Ensure ELF raw-dylib is able to link against a non-existent verbatim absolute path +//! by embedding the absolute path in the DT_SONAME and passing a different path for +//! the linker for the stub. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // The verbatim library name is an absolute path. + rustc().crate_type("bin").input("main.rs").run(); + + // FIXME(raw_dylib_elf): Read the NEEDED of the library to ensure it's the absolute path. +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/library.c b/tests/run-make/raw-dylib-elf-verbatim/library.c new file mode 100644 index 0000000000000..2e3a95b7edeca --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/library.c @@ -0,0 +1,3 @@ +int this_is_a_library_function() { + return 42; +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/main.rs b/tests/run-make/raw-dylib-elf-verbatim/main.rs new file mode 100644 index 0000000000000..044b7400a8412 --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "liblibrary.so.1", kind = "raw-dylib", modifiers = "+verbatim")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf-verbatim/output.txt b/tests/run-make/raw-dylib-elf-verbatim/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf-verbatim/rmake.rs b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs new file mode 100644 index 0000000000000..a6573e28359aa --- /dev/null +++ b/tests/run-make/raw-dylib-elf-verbatim/rmake.rs @@ -0,0 +1,26 @@ +//@ only-elf + +//! Ensure ELF raw-dylib is able to link against the verbatim versioned library +//! without it being present, and then be executed against this library. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, rfs, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // We also set the rpath to the current directory so we can pick up the library at runtime. + rustc() + .crate_type("bin") + .input("main.rs") + .arg(&format!("-Wl,-rpath={}", cwd().display())) + .run(); + + // Now, *after* building the binary, we build the library... + build_native_dynamic_lib("library"); + // ... rename it to have the versioned library name... + rfs::rename("liblibrary.so", "liblibrary.so.1"); + + // ... and run with this library, ensuring it was linked correctly at runtime. + let output = run("main").stdout_utf8(); + + diff().expected_file("output.txt").actual_text("actual", output).run(); +} diff --git a/tests/run-make/raw-dylib-elf/library.c b/tests/run-make/raw-dylib-elf/library.c new file mode 100644 index 0000000000000..2e3a95b7edeca --- /dev/null +++ b/tests/run-make/raw-dylib-elf/library.c @@ -0,0 +1,3 @@ +int this_is_a_library_function() { + return 42; +} diff --git a/tests/run-make/raw-dylib-elf/main.rs b/tests/run-make/raw-dylib-elf/main.rs new file mode 100644 index 0000000000000..3be944d295148 --- /dev/null +++ b/tests/run-make/raw-dylib-elf/main.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[link(name = "library", kind = "raw-dylib")] +unsafe extern "C" { + safe fn this_is_a_library_function() -> core::ffi::c_int; +} + +fn main() { + println!("{}", this_is_a_library_function()) +} diff --git a/tests/run-make/raw-dylib-elf/output.txt b/tests/run-make/raw-dylib-elf/output.txt new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/run-make/raw-dylib-elf/output.txt @@ -0,0 +1 @@ +42 diff --git a/tests/run-make/raw-dylib-elf/rmake.rs b/tests/run-make/raw-dylib-elf/rmake.rs new file mode 100644 index 0000000000000..96ae9f446f3b9 --- /dev/null +++ b/tests/run-make/raw-dylib-elf/rmake.rs @@ -0,0 +1,24 @@ +//@ only-elf + +//! Ensure ELF raw-dylib is able to link the binary without having the library present, +//! and then successfully run against the real library. + +use run_make_support::{build_native_dynamic_lib, cwd, diff, run, rustc}; + +fn main() { + // We compile the binary without having the library present. + // We also set the rpath to the current directory so we can pick up the library at runtime. + rustc() + .crate_type("bin") + .input("main.rs") + .arg(&format!("-Wl,-rpath={}", cwd().display())) + .run(); + + // Now, *after* building the binary, we build the library... + build_native_dynamic_lib("library"); + + // ... and run with this library, ensuring it was linked correctly at runtime. + let output = run("main").stdout_utf8(); + + diff().expected_file("output.txt").actual_text("actual", output).run(); +} diff --git a/tests/run-make/reproducible-build/linker.rs b/tests/run-make/reproducible-build/linker.rs index ab3b4049cc321..2f57d9f9be9a4 100644 --- a/tests/run-make/reproducible-build/linker.rs +++ b/tests/run-make/reproducible-build/linker.rs @@ -17,6 +17,8 @@ fn main() { for arg in env::args().skip(1) { let path = Path::new(&arg); if !path.is_file() { + // This directory is produced during linking in a temporary directory (ELF only). + let arg = if arg.ends_with("/raw-dylibs") { "/raw-dylibs" } else { &*arg }; out.push_str(&arg); out.push_str("\n"); continue; diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs new file mode 100644 index 0000000000000..a9ac5ce8b8337 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.rs @@ -0,0 +1,8 @@ +//@ only-elf + +#[link(name = "meow", kind = "raw-dylib")] //~ ERROR: link kind `raw-dylib` is unstable on ELF platforms +unsafe extern "C" { + safe fn meowmeow(); +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr new file mode 100644 index 0000000000000..63d9183511ef1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-raw-dylib-elf.stderr @@ -0,0 +1,13 @@ +error[E0658]: link kind `raw-dylib` is unstable on ELF platforms + --> $DIR/feature-gate-raw-dylib-elf.rs:3:30 + | +LL | #[link(name = "meow", kind = "raw-dylib")] + | ^^^^^^^^^^^ + | + = note: see issue #135694 for more information + = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs new file mode 100644 index 0000000000000..74aaf171f67b1 --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/multiple-libraries.rs @@ -0,0 +1,33 @@ +//@ only-elf + +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + + +#[cfg_attr(with, link(name = "rawdylibbutfordogs", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutfordogs"))] +unsafe extern "C" { + safe fn woooooooooooooooooof(); +} + +fn main() { + meooooooooooooooow(); + woooooooooooooooooof(); +} diff --git a/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs new file mode 100644 index 0000000000000..3ef43b9520495 --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/single-symbol.rs @@ -0,0 +1,25 @@ +//@ only-elf + +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + +fn main() { + meooooooooooooooow(); +} diff --git a/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs new file mode 100644 index 0000000000000..bc82d5f9cd3bf --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/elf/verbatim.rs @@ -0,0 +1,25 @@ +//@ only-elf + +//@ revisions: with without + +//@ [without] build-fail +//@ [without] regex-error-pattern:error: linking with `.*` failed +//@ [without] dont-check-compiler-stderr + +//@ [with] build-pass + +//! Ensures that linking fails when there's an undefined symbol, +//! and that it does succeed with raw-dylib, but with verbatim. + +#![feature(raw_dylib_elf)] +#![allow(incomplete_features)] + +#[cfg_attr(with, link(name = "rawdylibbutforcats", kind = "raw-dylib", modifiers = "+verbatim"))] +#[cfg_attr(without, link(name = "rawdylibbutforcats", modifiers = "+verbatim"))] +unsafe extern "C" { + safe fn meooooooooooooooow(); +} + +fn main() { + meooooooooooooooow(); +} diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs rename to tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr b/tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/dlltool-failed.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-invalid-format.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-multiple.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unknown-value.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-unsupported-link-kind.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.rs rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/import-name-type-x86-only.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.rs rename to tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr b/tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/invalid-dlltool.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/invalid-dlltool.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-and-name.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-and-name.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-missing-argument.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-multiple.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-multiple.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-not-foreign-fn.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-large.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-large.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-too-many-arguments.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.rs rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/link-ordinal-unsupported-link-kind.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-unsupported-link-kind.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.rs rename to tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr b/tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/multiple-declarations.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/multiple-declarations.stderr diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr new file mode 100644 index 0000000000000..70945ed6fc0bc --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.elf.stderr @@ -0,0 +1,13 @@ +error[E0658]: link kind `raw-dylib` is unstable on ELF platforms + --> $DIR/raw-dylib-windows-only.rs:6:29 + | +LL | #[link(name = "foo", kind = "raw-dylib")] + | ^^^^^^^^^^^ + | + = note: see issue #135694 for more information + = help: add `#![feature(raw_dylib_elf)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs new file mode 100644 index 0000000000000..935c59b5aaa5e --- /dev/null +++ b/tests/ui/linkage-attr/raw-dylib/windows/raw-dylib-windows-only.rs @@ -0,0 +1,9 @@ +//@ revisions: elf notelf +//@ [elf] only-elf +//@ [notelf] ignore-windows +//@ [notelf] ignore-elf +//@ compile-flags: --crate-type lib +#[link(name = "foo", kind = "raw-dylib")] +//[notelf]~^ ERROR: link kind `raw-dylib` is only supported on Windows targets +//[elf]~^^ ERROR: link kind `raw-dylib` is unstable on ELF platforms +extern "C" {} diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.rs rename to tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.rs diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr b/tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr similarity index 100% rename from tests/ui/rfcs/rfc-2627-raw-dylib/unsupported-abi.stderr rename to tests/ui/linkage-attr/raw-dylib/windows/unsupported-abi.stderr diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs deleted file mode 100644 index 3b982857db8dc..0000000000000 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ ignore-windows -//@ compile-flags: --crate-type lib -#[link(name = "foo", kind = "raw-dylib")] -//~^ ERROR: link kind `raw-dylib` is only supported on Windows targets -extern "C" {} diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr deleted file mode 100644 index ede20cb8c3f76..0000000000000 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0455]: link kind `raw-dylib` is only supported on Windows targets - --> $DIR/raw-dylib-windows-only.rs:3:29 - | -LL | #[link(name = "foo", kind = "raw-dylib")] - | ^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0455`. From 7de67a16c57872a0529384bac04bbbe01eebc221 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 12:51:58 +1100 Subject: [PATCH 20/22] Flatten the option check in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2c..f8f00c02ad2c8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -159,38 +159,35 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { (Option>, Option>, Option), ErrorGuaranteed, > { - match expr { - None => Ok((None, None, None)), - Some(expr) => { - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); - } - }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + let Some(expr) = expr else { return Ok((None, None, None)) }; + + let (kind, ascr, inline_const) = match self.lower_lit(expr) { + PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { + (subpattern.kind, None, def_id.as_local()) } - } + PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { + (subpattern.kind, None, None) + } + PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { + (kind, Some(ascription), None) + } + kind => (kind, None, None), + }; + let value = match kind { + PatKind::Constant { value } => value, + PatKind::ExpandedConstant { subpattern, .. } + if let PatKind::Constant { value } = subpattern.kind => + { + value + } + _ => { + let msg = format!( + "found bad range pattern endpoint `{expr:?}` outside of error recovery" + ); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + } + }; + Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we From 85f4cdc62692f27e897ba0da2cd5fae30a19f740 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:18:04 +1100 Subject: [PATCH 21/22] Return range endpoint ascriptions/consts via a `&mut Vec` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f8f00c02ad2c8..3aa2b343b557a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -155,11 +155,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range_endpoint( &mut self, expr: Option<&'tcx hir::PatExpr<'tcx>>, - ) -> Result< - (Option>, Option>, Option), - ErrorGuaranteed, - > { - let Some(expr) = expr else { return Ok((None, None, None)) }; + // Out-parameters collecting extra data to be reapplied by the caller + ascriptions: &mut Vec>, + inline_consts: &mut Vec, + ) -> Result>, ErrorGuaranteed> { + let Some(expr) = expr else { return Ok(None) }; let (kind, ascr, inline_const) = match self.lower_lit(expr) { PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { @@ -187,7 +187,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); } }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + + ascriptions.extend(ascr); + inline_consts.extend(inline_const); + Ok(Some(PatRangeBoundary::Finite(value))) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we @@ -250,11 +253,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.tcx.dcx().span_bug(span, msg); } - let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?; - let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?; + // Collect extra data while lowering the endpoints, to be reapplied later. + let mut ascriptions = vec![]; + let mut inline_consts = vec![]; + + let mut lower_endpoint = + |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts); - let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); - let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); + let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity); + let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity); let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); @@ -295,13 +302,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // If we are handling a range with associated constants (e.g. // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated // constants somewhere. Have them on the range pattern. - for ascription in [lo_ascr, hi_ascr].into_iter().flatten() { + for ascription in ascriptions { kind = PatKind::AscribeUserType { ascription, subpattern: Box::new(Pat { span, ty, kind }), }; } - for def in [lo_inline, hi_inline].into_iter().flatten() { + for def in inline_consts { kind = PatKind::ExpandedConstant { def_id: def.to_def_id(), is_inline: true, From 2fb1261c2156087d003359db25b13b282934669c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:29:13 +1100 Subject: [PATCH 22/22] Simplify the pattern unpeeling in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3aa2b343b557a..0aa61152330a7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -161,35 +161,34 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ) -> Result>, ErrorGuaranteed> { let Some(expr) = expr else { return Ok(None) }; - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + // Lower the endpoint into a temporary `PatKind` that will then be + // deconstructed to obtain the constant value and other data. + let mut kind: PatKind<'tcx> = self.lower_lit(expr); + + // Unpeel any ascription or inline-const wrapper nodes. + loop { + match kind { + PatKind::AscribeUserType { ascription, subpattern } => { + ascriptions.push(ascription); + kind = subpattern.kind; + } + PatKind::ExpandedConstant { is_inline, def_id, subpattern } => { + if is_inline { + inline_consts.extend(def_id.as_local()); + } + kind = subpattern.kind; + } + _ => break, } + } + + // The unpeeled kind should now be a constant, giving us the endpoint value. + let PatKind::Constant { value } = kind else { + let msg = + format!("found bad range pattern endpoint `{expr:?}` outside of error recovery"); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); }; - ascriptions.extend(ascr); - inline_consts.extend(inline_const); Ok(Some(PatRangeBoundary::Finite(value))) }