From dc49fdd2256bde48d90dde356355d6fc31e8f855 Mon Sep 17 00:00:00 2001
From: Sayantan Chakraborty <142906350+sayantn@users.noreply.github.com>
Date: Fri, 27 Dec 2024 11:47:34 +0530
Subject: [PATCH 01/68] Add `kl` and `widekl` target features, and the feature
gate
---
compiler/rustc_feature/src/unstable.rs | 2 ++
compiler/rustc_span/src/symbol.rs | 1 +
compiler/rustc_target/src/target_features.rs | 2 ++
tests/ui/check-cfg/target_feature.stderr | 2 ++
.../ui/feature-gates/feature-gate-keylocker_x86.rs | 6 ++++++
.../feature-gates/feature-gate-keylocker_x86.stderr | 13 +++++++++++++
6 files changed, 26 insertions(+)
create mode 100644 tests/ui/feature-gates/feature-gate-keylocker_x86.rs
create mode 100644 tests/ui/feature-gates/feature-gate-keylocker_x86.stderr
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d40823d2ed62..6807339c668c 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -525,6 +525,8 @@ declare_features! (
(unstable, inline_const_pat, "1.58.0", Some(76001)),
/// Allows using `pointer` and `reference` in intra-doc links
(unstable, intra_doc_pointers, "1.51.0", Some(80896)),
+ // Allows using the `kl` and `widekl` target features and the associated intrinsics
+ (unstable, keylocker_x86, "CURRENT_RUSTC_VERSION", Some(134813)),
// Allows setting the threshold for the `large_assignments` lint.
(unstable, large_assignments, "1.52.0", Some(83518)),
/// Allow to have type alias types for inter-crate use.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bdfbfb1e38dd..cb0c5ae6ad13 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1149,6 +1149,7 @@ symbols! {
iterator,
iterator_collect_fn,
kcfi,
+ keylocker_x86,
keyword,
kind,
kreg,
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index f594d20f9286..69ff03e7e24b 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -401,6 +401,7 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("fma", Stable, &["avx"]),
("fxsr", Stable, &[]),
("gfni", Unstable(sym::avx512_target_feature), &["sse2"]),
+ ("kl", Unstable(sym::keylocker_x86), &["sse2"]),
("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
("lzcnt", Stable, &[]),
("movbe", Stable, &[]),
@@ -425,6 +426,7 @@ const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("tbm", Unstable(sym::tbm_target_feature), &[]),
("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
+ ("widekl", Unstable(sym::keylocker_x86), &["kl"]),
("x87", Unstable(sym::x87_target_feature), &[]),
("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
("xsave", Stable, &[]),
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 70fec8a350aa..7c1588781f5b 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -127,6 +127,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`isa-68881`
`isa-68882`
`jsconv`
+`kl`
`lahfsahf`
`lasx`
`lbt`
@@ -270,6 +271,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`vsx`
`wfxt`
`wide-arithmetic`
+`widekl`
`x87`
`xop`
`xsave`
diff --git a/tests/ui/feature-gates/feature-gate-keylocker_x86.rs b/tests/ui/feature-gates/feature-gate-keylocker_x86.rs
new file mode 100644
index 000000000000..cef80ad41a89
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-keylocker_x86.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "kl")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-keylocker_x86.stderr b/tests/ui/feature-gates/feature-gate-keylocker_x86.stderr
new file mode 100644
index 000000000000..ed814d3a3ce2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-keylocker_x86.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `kl` is currently unstable
+ --> $DIR/feature-gate-keylocker_x86.rs:2:18
+ |
+LL | #[target_feature(enable = "kl")]
+ | ^^^^^^^^^^^^^
+ |
+ = note: see issue #134813 for more information
+ = help: add `#![feature(keylocker_x86)]` 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`.
From 57e857576000b3a879de3fe7a9b641ecd645474c 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: Sun, 26 Jan 2025 14:41:41 +0800
Subject: [PATCH 02/68] features-status-dump: add new build-metrics tool
Co-authored-by: Jane Losare-Lusby
---
Cargo.lock | 15 ++++++
Cargo.toml | 1 +
src/tools/features-status-dump/Cargo.toml | 12 +++++
src/tools/features-status-dump/src/main.rs | 53 ++++++++++++++++++++++
4 files changed, 81 insertions(+)
create mode 100644 src/tools/features-status-dump/Cargo.toml
create mode 100644 src/tools/features-status-dump/src/main.rs
diff --git a/Cargo.lock b/Cargo.lock
index 979198cece80..9b6dbc33b426 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -186,6 +186,9 @@ name = "anyhow"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+dependencies = [
+ "backtrace",
+]
[[package]]
name = "ar_archive_writer"
@@ -1195,6 +1198,17 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+[[package]]
+name = "features-status-dump"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "serde",
+ "serde_json",
+ "tidy",
+]
+
[[package]]
name = "field-offset"
version = "0.3.6"
@@ -5373,6 +5387,7 @@ dependencies = [
"regex",
"rustc-hash 2.1.0",
"semver",
+ "serde",
"similar",
"termcolor",
"walkdir",
diff --git a/Cargo.toml b/Cargo.toml
index b773030b4cab..68d142ebe926 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,6 +47,7 @@ members = [
"src/tools/coverage-dump",
"src/tools/rustc-perf-wrapper",
"src/tools/wasm-component-ld",
+ "src/tools/features-status-dump",
]
exclude = [
diff --git a/src/tools/features-status-dump/Cargo.toml b/src/tools/features-status-dump/Cargo.toml
new file mode 100644
index 000000000000..35be71a46e55
--- /dev/null
+++ b/src/tools/features-status-dump/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "features-status-dump"
+version = "0.1.0"
+license = "MIT OR Apache-2.0"
+edition = "2021"
+
+[dependencies]
+anyhow = { version = "1", features = ["backtrace"] }
+clap = { version = "4", features = ["derive"] }
+serde = { version = "1.0.125", features = [ "derive" ] }
+serde_json = "1.0.59"
+tidy = { path = "../tidy", features = ["build-metrics"] }
diff --git a/src/tools/features-status-dump/src/main.rs b/src/tools/features-status-dump/src/main.rs
new file mode 100644
index 000000000000..1ce98d1506d1
--- /dev/null
+++ b/src/tools/features-status-dump/src/main.rs
@@ -0,0 +1,53 @@
+use std::collections::HashMap;
+use std::fs::File;
+use std::io::BufWriter;
+use std::path::PathBuf;
+
+use anyhow::{Context, Result};
+use clap::Parser;
+use tidy::features::{Feature, collect_lang_features, collect_lib_features};
+
+#[derive(Debug, Parser)]
+struct Cli {
+ /// Path to `library/` directory.
+ #[arg(long)]
+ library_path: PathBuf,
+ /// Path to `compiler/` directory.
+ #[arg(long)]
+ compiler_path: PathBuf,
+ /// Path to `output/` directory.
+ #[arg(long)]
+ output_path: PathBuf,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct FeaturesStatus {
+ lang_features_status: HashMap,
+ lib_features_status: HashMap,
+}
+
+fn main() -> Result<()> {
+ let Cli { compiler_path, library_path, output_path } = Cli::parse();
+
+ let lang_features_status = collect_lang_features(&compiler_path, &mut false);
+ let lib_features_status = collect_lib_features(&library_path)
+ .into_iter()
+ .filter(|&(ref name, _)| !lang_features_status.contains_key(name))
+ .collect();
+ let features_status = FeaturesStatus { lang_features_status, lib_features_status };
+
+ let output_dir = output_path.parent().with_context(|| {
+ format!("failed to get parent dir of output path `{}`", output_path.display())
+ })?;
+ std::fs::create_dir_all(output_dir).with_context(|| {
+ format!("failed to create output directory at `{}`", output_dir.display())
+ })?;
+
+ let output_file = File::create(&output_path).with_context(|| {
+ format!("failed to create file at given output path `{}`", output_path.display())
+ })?;
+ let writer = BufWriter::new(output_file);
+ serde_json::to_writer_pretty(writer, &features_status)
+ .context("failed to write json output")?;
+ Ok(())
+}
From 93563980a33e4b6cf8e3fbfa02bd4479ebd05a70 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: Sun, 26 Jan 2025 14:42:01 +0800
Subject: [PATCH 03/68] tidy: add `build-metrics`-gated feature status
serialization
Co-authored-by: Jane Losare-Lusby
---
src/tools/tidy/Cargo.toml | 4 ++++
src/tools/tidy/src/features.rs | 2 ++
src/tools/tidy/src/features/version.rs | 1 +
3 files changed, 7 insertions(+)
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 2f424a482b5b..9a4d0891b4ae 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -12,11 +12,15 @@ miropt-test-tools = { path = "../miropt-test-tools" }
walkdir = "2"
ignore = "0.4.18"
semver = "1.0"
+serde = { version = "1.0.125", features = ["derive"], optional = true }
termcolor = "1.1.3"
rustc-hash = "2.0.0"
fluent-syntax = "0.11.1"
similar = "2.5.0"
+[features]
+build-metrics = ["dep:serde"]
+
[[bin]]
name = "rust-tidy"
path = "src/main.rs"
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 4f24eb212420..fcd7943e6e0a 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -27,6 +27,7 @@ const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start";
const FEATURE_GROUP_END_PREFIX: &str = "// feature-group-end";
#[derive(Debug, PartialEq, Clone)]
+#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
pub enum Status {
Accepted,
Removed,
@@ -45,6 +46,7 @@ impl fmt::Display for Status {
}
#[derive(Debug, Clone)]
+#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
pub struct Feature {
pub level: Status,
pub since: Option,
diff --git a/src/tools/tidy/src/features/version.rs b/src/tools/tidy/src/features/version.rs
index 0830c226caf4..6a902e80f8e7 100644
--- a/src/tools/tidy/src/features/version.rs
+++ b/src/tools/tidy/src/features/version.rs
@@ -8,6 +8,7 @@ mod tests;
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+#[cfg_attr(feature = "build-metrics", derive(serde::Serialize))]
pub enum Version {
Explicit { parts: [u32; 3] },
CurrentPlaceholder,
From cbcba57c0549ff24283796ba62c28d30d65d7feb 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: Sun, 26 Jan 2025 14:42:46 +0800
Subject: [PATCH 04/68] bootstrap: wire up `src/tools/features-status-dump` as
a runnable tool
And also register its check step.
Co-authored-by: Jane Losare-Lusby
---
src/bootstrap/src/core/build_steps/check.rs | 1 +
src/bootstrap/src/core/build_steps/run.rs | 31 +++++++++++++++++++++
src/bootstrap/src/core/build_steps/tool.rs | 1 +
src/bootstrap/src/core/builder/mod.rs | 2 ++
4 files changed, 35 insertions(+)
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index d8d862caf6a9..c3304d51dade 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -455,6 +455,7 @@ tool_check_step!(Rls { path: "src/tools/rls" });
tool_check_step!(Rustfmt { path: "src/tools/rustfmt" });
tool_check_step!(MiroptTestTools { path: "src/tools/miropt-test-tools" });
tool_check_step!(TestFloatParse { path: "src/etc/test-float-parse" });
+tool_check_step!(FeaturesStatusDump { path: "src/tools/features-status-dump" });
tool_check_step!(Bootstrap { path: "src/bootstrap", default: false });
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index 8513c59808c6..167b8a5b168c 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -311,3 +311,34 @@ impl Step for UnicodeTableGenerator {
cmd.run(builder);
}
}
+
+#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
+pub struct FeaturesStatusDump;
+
+impl Step for FeaturesStatusDump {
+ type Output = ();
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.path("src/tools/features-status-dump")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(FeaturesStatusDump);
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ let mut cmd = builder.tool_cmd(Tool::FeaturesStatusDump);
+
+ cmd.arg("--library-path");
+ cmd.arg(builder.src.join("library"));
+
+ cmd.arg("--compiler-path");
+ cmd.arg(builder.src.join("compiler"));
+
+ cmd.arg("--output-path");
+ cmd.arg(builder.out.join("features-status-dump.json"));
+
+ cmd.run(builder);
+ }
+}
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 9ae03ac7fe07..937dae833647 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -363,6 +363,7 @@ bootstrap_tool!(
RustcPerfWrapper, "src/tools/rustc-perf-wrapper", "rustc-perf-wrapper";
WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
+ FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
);
/// These are the submodules that are required for rustbook to work due to
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index b293ac4f3515..050965770bac 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -938,6 +938,7 @@ impl<'a> Builder<'a> {
check::Bootstrap,
check::RunMakeSupport,
check::Compiletest,
+ check::FeaturesStatusDump,
),
Kind::Test => describe!(
crate::core::build_steps::toolstate::ToolStateCheck,
@@ -1089,6 +1090,7 @@ impl<'a> Builder<'a> {
run::GenerateWindowsSys,
run::GenerateCompletions,
run::UnicodeTableGenerator,
+ run::FeaturesStatusDump,
),
Kind::Setup => {
describe!(setup::Profile, setup::Hook, setup::Link, setup::Editor)
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 05/68] 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 bbd506127fb6..c665dfd36247 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 d02172610687..000000000000
--- 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 44fe84c989fb..688c326a26aa 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 06/68] 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 b3e63aaf1c56..def5f984c88e 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 88a9f33c0790..8fd6eb3c0206 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 07/68] 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 da58d7c13bd1..9c1b04b2742f 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 4f37e18a8cd7..5a3626ccc1f3 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 42cd6e3fe2a5..56b11ae170f8 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 438d77b1626b..1842a079dbc8 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 9bb4bfbab2a0..cb62b2cc9df3 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 1b0d7f3dbf2c..e0f9f0bb5cee 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 d2f679e7dde5..dd76081532f5 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 cbcf9f96239b..d0e8b157e6b6 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 684ee3f3855b..5180f3d40f3a 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 99cfcfb231da..bf7641986ada 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 f5ba2c7b594e..cbbfcd15efd2 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 000000000000..79813871ed94
--- /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 08/68] 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 dd76081532f5..ffb8789c906e 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 df0df3f23f75..a7400f1c02df 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 09/68] 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 d649357a56d7..153189b8b031 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 b37d74011cc6..f13b931dd222 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 10/68] 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} | 147 +++---------------
4 files changed, 138 insertions(+), 127 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 1b21c230a0bf..ae000d24d281 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 000000000000..094c00894a8e
--- /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 7fd08a97f1f2..97e17acadeac 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 3f96ac4672af..978402b6fdae 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/tests/path.rs
@@ -1,10 +1,19 @@
-use core::hint::black_box;
+#![feature(
+ clone_to_uninit,
+ path_add_extension,
+ path_file_prefix,
+ maybe_uninit_slice,
+ os_string_pathbuf_leak
+)]
-use super::*;
-use crate::collections::{BTreeSet, HashSet};
-use crate::hash::DefaultHasher;
-use crate::mem::MaybeUninit;
-use crate::ptr;
+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 11/68] 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 ae000d24d281..e749d9c0f799 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 000000000000..552481cad928
--- /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 9f4f8a0d0880..88b3e9e0ceba 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 e88f2d5e8067..40709eae37cf 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 12/68] 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 9c1b04b2742f..be6c2aad8713 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 c003503ca8b0..ca04aa4ada49 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 dd1800416482..454462b39251 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 000000000000..c52914354253
--- /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 9d4f52a09218..aa020c2559cc 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 13/68] 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 be6c2aad8713..7648dc141d8c 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 862753e4765d..067ff66d9af7 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 98c83d8d326c..78cf8841efef 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 c86b546e0116..f942937c14d1 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 49f2dafd8fd9..f6e4b34a13a3 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 a6e2389c93ba..7f0f3f652bcb 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 01ef71a187fe..0a5ad5619265 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 27db4b634fb2..f78d88ac6d89 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 1519baf99a8f..f9d9321f5f2d 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 0140e0d21299..e009eb410efc 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 0fbcd9988127..8aefff9d5071 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 f9e9066bc92a..834de6bb1c29 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 7d7dde543499..6c14b79f2ce7 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 000000000000..6bf320d52f21
--- /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 ab14050df6c9..81b92297f76a 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 13892fa0d18e..1d8edfde44be 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 49b65c8efe69..a7f326d201b0 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 395c8aada089..74c627201073 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 ce96468aeb6e..a3ffc73fe06b 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 5113d436c3c9..1ce273b5a7a4 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 aeef0289d28f..2b7b87e36234 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 057c2f1a5d7a..bd4bc7a14bc8 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 14/68] 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 7648dc141d8c..67c249d54a04 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 15/68] 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 1ce273b5a7a4..ac9aaa8892ef 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 16/68] 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 688c326a26aa..e754cf8263b0 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 000000000000..607474473500
--- /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 0bb3d5209e60c41d60b679453fd9e15af16866e6 Mon Sep 17 00:00:00 2001
From: Samuel Tardieu
Date: Fri, 10 Jan 2025 23:53:14 +0100
Subject: [PATCH 17/68] Remove `LateContext::match_def_path()`
This function was only kept for Clippy use. The last use in Clippy was
removed in c9315bc3953fcf15154df21f788f2f7a5e8d6e7d.
---
compiler/rustc_lint/src/context.rs | 26 +-------------------------
1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 50bb1fb942e9..e0863aa035c1 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -4,7 +4,7 @@
//! overview of how lints are implemented.
use std::cell::Cell;
-use std::{iter, slice};
+use std::slice;
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::sync;
@@ -718,30 +718,6 @@ impl<'tcx> LateContext<'tcx> {
}
}
- /// Check if a `DefId`'s path matches the given absolute type path usage.
- ///
- /// Anonymous scopes such as `extern` imports are matched with `kw::Empty`;
- /// inherent `impl` blocks are matched with the name of the type.
- ///
- /// Instead of using this method, it is often preferable to instead use
- /// `rustc_diagnostic_item` or a `lang_item`. This is less prone to errors
- /// as paths get invalidated if the target definition moves.
- ///
- /// # Examples
- ///
- /// ```rust,ignore (no context or def id available)
- /// if cx.match_def_path(def_id, &[sym::core, sym::option, sym::Option]) {
- /// // The given `def_id` is that of an `Option` type
- /// }
- /// ```
- ///
- /// Used by clippy, but should be replaced by diagnostic items eventually.
- pub fn match_def_path(&self, def_id: DefId, path: &[Symbol]) -> bool {
- let names = self.get_def_path(def_id);
-
- names.len() == path.len() && iter::zip(names, path).all(|(a, &b)| a == b)
- }
-
/// Gets the absolute path of `def_id` as a vector of `Symbol`.
///
/// # Examples
From 962fec2193137c6fe2bcf56552671178e89f70cc Mon Sep 17 00:00:00 2001
From: "Pascal S. de Kloe"
Date: Wed, 8 Jan 2025 19:27:11 +0100
Subject: [PATCH 18/68] black_box integer-input on fmt benches
---
library/coretests/benches/fmt.rs | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/library/coretests/benches/fmt.rs b/library/coretests/benches/fmt.rs
index ed478b0f1e05..ee8e981b46b9 100644
--- a/library/coretests/benches/fmt.rs
+++ b/library/coretests/benches/fmt.rs
@@ -124,42 +124,41 @@ fn write_str_macro_debug_ascii(bh: &mut Bencher) {
#[bench]
fn write_u128_max(bh: &mut Bencher) {
bh.iter(|| {
- test::black_box(format!("{}", u128::MAX));
+ black_box(format!("{}", black_box(u128::MAX)));
});
}
#[bench]
fn write_u128_min(bh: &mut Bencher) {
bh.iter(|| {
- let s = format!("{}", 0u128);
- test::black_box(s);
+ black_box(format!("{}", black_box(u128::MIN)));
});
}
#[bench]
fn write_u64_max(bh: &mut Bencher) {
bh.iter(|| {
- test::black_box(format!("{}", u64::MAX));
+ black_box(format!("{}", black_box(u64::MAX)));
});
}
#[bench]
fn write_u64_min(bh: &mut Bencher) {
bh.iter(|| {
- test::black_box(format!("{}", 0u64));
+ black_box(format!("{}", black_box(u64::MIN)));
});
}
#[bench]
fn write_u8_max(bh: &mut Bencher) {
bh.iter(|| {
- test::black_box(format!("{}", u8::MAX));
+ black_box(format!("{}", black_box(u8::MAX)));
});
}
#[bench]
fn write_u8_min(bh: &mut Bencher) {
bh.iter(|| {
- test::black_box(format!("{}", 0u8));
+ black_box(format!("{}", black_box(u8::MIN)));
});
}
From a063cf5f1c151873f753905c75d8e67115308f9d Mon Sep 17 00:00:00 2001
From: "Alexis (Poliorcetics) Bourget"
Date: Thu, 26 Dec 2024 23:41:58 +0100
Subject: [PATCH 19/68] 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 7853e311a040..f13428fc4203 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 77040aeb94d7..65722eff1dab 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 0437ebb58576..d6b2b53d34cb 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 b4bc0b80d6c6..d957cf1b569e 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 5d96dbc0ee65..1cefdf96bbcd 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> {
\
\
You need to enable JavaScript to use keyboard commands or search.
\
- For more information, browse the rustdoc handbook .
\
+ For more information, browse the rustdoc handbook .
\
\
",
)
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a27a9d202eb8..f7dcb87e4f3d 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 37fea09ace31..c50adf116160 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 ccf4002bb300..bfd5cb7764fd 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 1ad32721e068..662e95106997 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 9c62826ccc2e..0034552bdd3b 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 9c2b39edc9f3..5256b6c8f2ac 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 bb954a31891a..45f42e61fbf7 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 a777b45b8070..9fe8b99e8af8 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 5f34c8b99e0f..6de435dbcc14 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 139d6ba054a1a4cc5fe64981ad46fd5547bd4916 Mon Sep 17 00:00:00 2001
From: onur-ozkan
Date: Thu, 30 Jan 2025 16:51:08 +0000
Subject: [PATCH 20/68] set rustc dylib on manually constructed rustc command
Signed-off-by: onur-ozkan
---
src/bootstrap/src/core/builder/cargo.rs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 1b413dcb07ef..79a65aedd9ed 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -653,7 +653,10 @@ impl Builder<'_> {
// Build proc macros both for the host and the target unless proc-macros are not
// supported by the target.
if target != compiler.host && cmd_kind != Kind::Check {
- let error = command(self.rustc(compiler))
+ let mut rustc_cmd = command(self.rustc(compiler));
+ self.add_rustc_lib_path(compiler, &mut rustc_cmd);
+
+ let error = rustc_cmd
.arg("--target")
.arg(target.rustc_target_arg())
.arg("--print=file-names")
@@ -661,6 +664,7 @@ impl Builder<'_> {
.arg("-")
.run_capture(self)
.stderr();
+
let not_supported = error
.lines()
.any(|line| line.contains("unsupported crate type `proc-macro`"));
From 95eaadc773eb4adab8f46cd77083d1d503fd5bff Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Sun, 26 Jan 2025 13:27:34 -0700
Subject: [PATCH 21/68] std::range
---
library/std/src/lib.rs | 2 ++
...ter.inclusive_loop.PreCodegen.after.panic-abort.mir | 10 +++++-----
...er.inclusive_loop.PreCodegen.after.panic-unwind.mir | 10 +++++-----
...nclusive_iter_next.PreCodegen.after.panic-abort.mir | 6 +++---
...clusive_iter_next.PreCodegen.after.panic-unwind.mir | 6 +++---
.../std/const-generics-range.full.stderr | 4 ++--
.../const-generics/std/const-generics-range.min.stderr | 4 ++--
tests/ui/const-generics/std/const-generics-range.rs | 4 ++--
tests/ui/issues/issue-76191.stderr | 4 ++--
...closure-arg-type-mismatch-issue-45727.current.fixed | 2 +-
.../closure-arg-type-mismatch-issue-45727.next.stderr | 8 ++++----
.../closure-arg-type-mismatch-issue-45727.rs | 2 +-
tests/ui/never_type/issue-52443.stderr | 4 ++--
tests/ui/range/issue-54505-no-literals.stderr | 8 ++++----
tests/ui/range/issue-54505.stderr | 4 ++--
tests/ui/range/range-1.stderr | 2 +-
.../unnecessary_dot_for_floating_point_literal.stderr | 2 +-
17 files changed, 42 insertions(+), 40 deletions(-)
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index acb3a0578e50..7c18226874cc 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -530,6 +530,8 @@ pub use core::option;
pub use core::pin;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::ptr;
+#[unstable(feature = "new_range_api", issue = "125687")]
+pub use core::range;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::result;
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
index 60c0b8afa534..3f000dcafb03 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir
@@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
scope 2 {
debug x => _9;
}
- scope 5 (inlined iter::range::>::next) {
+ scope 5 (inlined iter::range::>::next) {
}
}
- scope 3 (inlined RangeInclusive::::new) {
+ scope 3 (inlined std::ops::RangeInclusive::::new) {
}
- scope 4 (inlined as IntoIterator>::into_iter) {
+ scope 4 (inlined as IntoIterator>::into_iter) {
}
bb0: {
- _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
+ _4 = std::ops::RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
@@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
- _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
+ _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind unreachable];
}
bb2: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
index 7145da58ce18..235371736271 100644
--- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir
@@ -19,16 +19,16 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
scope 2 {
debug x => _9;
}
- scope 5 (inlined iter::range::>::next) {
+ scope 5 (inlined iter::range::>::next) {
}
}
- scope 3 (inlined RangeInclusive::::new) {
+ scope 3 (inlined std::ops::RangeInclusive::::new) {
}
- scope 4 (inlined as IntoIterator>::into_iter) {
+ scope 4 (inlined as IntoIterator>::into_iter) {
}
bb0: {
- _4 = RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
+ _4 = std::ops::RangeInclusive:: { start: copy _1, end: copy _2, exhausted: const false };
StorageLive(_5);
_5 = copy _4;
goto -> bb1;
@@ -37,7 +37,7 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
bb1: {
StorageLive(_7);
_6 = &mut _5;
- _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
+ _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _6) -> [return: bb2, unwind: bb8];
}
bb2: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
index 8e038246fa2d..13969e5d2385 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-abort.mir
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen
-fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option {
+fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option {
debug it => _1;
let mut _0: std::option::Option;
- scope 1 (inlined iter::range::>::next) {
+ scope 1 (inlined iter::range::>::next) {
}
bb0: {
- _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
+ _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind unreachable];
}
bb1: {
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
index f54d003c662f..98cd58284dfa 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_inclusive_iter_next.PreCodegen.after.panic-unwind.mir
@@ -1,13 +1,13 @@
// MIR for `range_inclusive_iter_next` after PreCodegen
-fn range_inclusive_iter_next(_1: &mut RangeInclusive) -> Option {
+fn range_inclusive_iter_next(_1: &mut std::ops::RangeInclusive) -> Option {
debug it => _1;
let mut _0: std::option::Option;
- scope 1 (inlined iter::range::>::next) {
+ scope 1 (inlined iter::range::>::next) {
}
bb0: {
- _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
+ _0 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(move _1) -> [return: bb1, unwind continue];
}
bb1: {
diff --git a/tests/ui/const-generics/std/const-generics-range.full.stderr b/tests/ui/const-generics/std/const-generics-range.full.stderr
index 5bf48ad73858..2b5c63e6643d 100644
--- a/tests/ui/const-generics/std/const-generics-range.full.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.full.stderr
@@ -4,7 +4,7 @@ error[E0741]: `std::ops::Range` must implement `ConstParamTy` to be used
LL | struct _Range>;
| ^^^^^^^^^^^^^^^^^^^^^^
-error[E0741]: `RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter
+error[E0741]: `std::ops::RangeFrom` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom>;
@@ -16,7 +16,7 @@ error[E0741]: `RangeFull` must implement `ConstParamTy` to be used as the type o
LL | struct _RangeFull;
| ^^^^^^^^^^^^^^^^^^^
-error[E0741]: `RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter
+error[E0741]: `std::ops::RangeInclusive` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive>;
diff --git a/tests/ui/const-generics/std/const-generics-range.min.stderr b/tests/ui/const-generics/std/const-generics-range.min.stderr
index fd23b9b248a0..04e3fe744534 100644
--- a/tests/ui/const-generics/std/const-generics-range.min.stderr
+++ b/tests/ui/const-generics/std/const-generics-range.min.stderr
@@ -10,7 +10,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|
-error: `RangeFrom` is forbidden as the type of a const generic parameter
+error: `std::ops::RangeFrom` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:13:28
|
LL | struct _RangeFrom>;
@@ -34,7 +34,7 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|
-error: `RangeInclusive` is forbidden as the type of a const generic parameter
+error: `std::ops::RangeInclusive` is forbidden as the type of a const generic parameter
--> $DIR/const-generics-range.rs:24:33
|
LL | struct _RangeInclusive>;
diff --git a/tests/ui/const-generics/std/const-generics-range.rs b/tests/ui/const-generics/std/const-generics-range.rs
index f959f1e2949a..3a238ed177e0 100644
--- a/tests/ui/const-generics/std/const-generics-range.rs
+++ b/tests/ui/const-generics/std/const-generics-range.rs
@@ -11,7 +11,7 @@ const RANGE : _Range<{ 0 .. 1000 }> = _Range;
// `RangeFrom` should be usable within const generics:
struct _RangeFrom>;
-//[min]~^ ERROR `RangeFrom` is forbidden
+//[min]~^ ERROR `std::ops::RangeFrom` is forbidden
const RANGE_FROM : _RangeFrom<{ 0 .. }> = _RangeFrom;
// `RangeFull` should be usable within const generics:
@@ -22,7 +22,7 @@ const RANGE_FULL : _RangeFull<{ .. }> = _RangeFull;
// Regression test for #70155
// `RangeInclusive` should be usable within const generics:
struct _RangeInclusive>;
-//[min]~^ ERROR `RangeInclusive` is forbidden
+//[min]~^ ERROR `std::ops::RangeInclusive` is forbidden
const RANGE_INCLUSIVE : _RangeInclusive<{ 0 ..= 999 }> = _RangeInclusive;
// `RangeTo` should be usable within const generics:
diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr
index 3702bfb77699..3b89ec7cb9c9 100644
--- a/tests/ui/issues/issue-76191.stderr
+++ b/tests/ui/issues/issue-76191.stderr
@@ -21,7 +21,7 @@ LL | RANGE => {}
| `RANGE` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
- found struct `RangeInclusive`
+ found struct `std::ops::RangeInclusive`
help: you may want to move the range into the match block
|
LL | 0..=255 => {}
@@ -43,7 +43,7 @@ LL | RANGE2 => {}
| `RANGE2` is interpreted as a constant, not a new binding
|
= note: expected type `i32`
- found struct `RangeInclusive`
+ found struct `std::ops::RangeInclusive`
= note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block
error: aborting due to 3 previous errors
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
index 25943d11fc47..fc44c824043b 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
@@ -5,7 +5,7 @@
fn main() {
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
- //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index 696214c0a3cd..973fe7ade602 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -1,14 +1,14 @@
-error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29
|
LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
+ = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
= note: expected a closure with arguments `(i32,)`
- found a closure with arguments `(& as Iterator>::Item,)`
+ found a closure with arguments `(& as Iterator>::Item,)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
index 9e44489cbf17..a96df10db355 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -5,7 +5,7 @@
fn main() {
let _ = (-10..=10).find(|x: i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
- //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~^^ ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr
index 1c5a0d65142f..bb60c33595c2 100644
--- a/tests/ui/never_type/issue-52443.stderr
+++ b/tests/ui/never_type/issue-52443.stderr
@@ -31,7 +31,7 @@ help: give the `break` a value of the expected type
LL | [(); loop { break 42 }];
| ++
-error[E0015]: cannot use `for` loop on `RangeFrom` in constants
+error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
@@ -39,7 +39,7 @@ LL | [(); { for _ in 0usize.. {}; 0}];
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
-error[E0015]: cannot use `for` loop on `RangeFrom` in constants
+error[E0015]: cannot use `for` loop on `std::ops::RangeFrom` in constants
--> $DIR/issue-52443.rs:9:21
|
LL | [(); { for _ in 0usize.. {}; 0}];
diff --git a/tests/ui/range/issue-54505-no-literals.stderr b/tests/ui/range/issue-54505-no-literals.stderr
index 5894bb6ba553..c6d4384bcd33 100644
--- a/tests/ui/range/issue-54505-no-literals.stderr
+++ b/tests/ui/range/issue-54505-no-literals.stderr
@@ -47,7 +47,7 @@ LL | take_range(std::ops::RangeFrom { start: 1 });
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -67,7 +67,7 @@ LL | take_range(::std::ops::RangeFrom { start: 1 });
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -127,7 +127,7 @@ LL | take_range(std::ops::RangeInclusive::new(0, 1));
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
@@ -147,7 +147,7 @@ LL | take_range(::std::ops::RangeInclusive::new(0, 1));
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505-no-literals.rs:12:4
|
diff --git a/tests/ui/range/issue-54505.stderr b/tests/ui/range/issue-54505.stderr
index 291e097e8659..8b669b2910f6 100644
--- a/tests/ui/range/issue-54505.stderr
+++ b/tests/ui/range/issue-54505.stderr
@@ -27,7 +27,7 @@ LL | take_range(1..);
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
note: function defined here
--> $DIR/issue-54505.rs:10:4
|
@@ -72,7 +72,7 @@ LL | take_range(0..=1);
| arguments to this function are incorrect
|
= note: expected reference `&_`
- found struct `RangeInclusive<{integer}>`
+ found struct `std::ops::RangeInclusive<{integer}>`
note: function defined here
--> $DIR/issue-54505.rs:10:4
|
diff --git a/tests/ui/range/range-1.stderr b/tests/ui/range/range-1.stderr
index f77601bc43cd..37669dd3f47c 100644
--- a/tests/ui/range/range-1.stderr
+++ b/tests/ui/range/range-1.stderr
@@ -30,7 +30,7 @@ LL | let range = *arr..;
| ^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[{integer}]`
-note: required by an implicit `Sized` bound in `RangeFrom`
+note: required by an implicit `Sized` bound in `std::ops::RangeFrom`
--> $SRC_DIR/core/src/ops/range.rs:LL:COL
error: aborting due to 3 previous errors
diff --git a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
index 8b48ee9f1247..c0162ec2cab8 100644
--- a/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
+++ b/tests/ui/suggestions/unnecessary_dot_for_floating_point_literal.stderr
@@ -22,7 +22,7 @@ LL | let _: f64 = 1..;
| expected due to this
|
= note: expected type `f64`
- found struct `RangeFrom<{integer}>`
+ found struct `std::ops::RangeFrom<{integer}>`
help: remove the unnecessary `.` operator for a floating point literal
|
LL | let _: f64 = 1.;
From f530a29944ff1eba9a146704ba2f13b94331be5d Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Mon, 27 Jan 2025 13:32:10 -0700
Subject: [PATCH 22/68] implement unstable `new_range` feature
for RFC 3550, tracking issue #123741
---
compiler/rustc_ast_lowering/src/expr.rs | 35 +++++++++++---
compiler/rustc_feature/src/unstable.rs | 2 +
compiler/rustc_hir/src/hir.rs | 41 +++++++++++++++-
compiler/rustc_hir/src/lang_items.rs | 5 ++
.../rustc_hir_typeck/src/method/suggest.rs | 4 ++
compiler/rustc_span/src/symbol.rs | 4 ++
library/core/src/range.rs | 3 ++
.../src/language-features/new-range.md | 9 ++++
.../feature-gates/feature-gate-new_range.rs | 10 ++++
.../feature-gate-new_range.stderr | 48 +++++++++++++++++++
...rg-type-mismatch-issue-45727.current.fixed | 2 +-
...-arg-type-mismatch-issue-45727.next.stderr | 8 ++--
.../closure-arg-type-mismatch-issue-45727.rs | 2 +-
tests/ui/new-range/disabled.rs | 27 +++++++++++
tests/ui/new-range/enabled.rs | 24 ++++++++++
15 files changed, 210 insertions(+), 14 deletions(-)
create mode 100644 src/doc/unstable-book/src/language-features/new-range.md
create mode 100644 tests/ui/feature-gates/feature-gate-new_range.rs
create mode 100644 tests/ui/feature-gates/feature-gate-new_range.stderr
create mode 100644 tests/ui/new-range/disabled.rs
create mode 100644 tests/ui/new-range/enabled.rs
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 1267281f73eb..98d6372ca896 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -284,9 +284,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
ExprKind::Index(el, er, brackets_span) => {
hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er), *brackets_span)
}
- ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => {
- self.lower_expr_range_closed(e.span, e1, e2)
- }
ExprKind::Range(e1, e2, lims) => {
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims)
}
@@ -1512,15 +1509,39 @@ impl<'hir> LoweringContext<'_, 'hir> {
let lang_item = match (e1, e2, lims) {
(None, None, HalfOpen) => hir::LangItem::RangeFull,
- (Some(..), None, HalfOpen) => hir::LangItem::RangeFrom,
+ (Some(..), None, HalfOpen) => {
+ if self.tcx.features().new_range() {
+ hir::LangItem::RangeFromCopy
+ } else {
+ hir::LangItem::RangeFrom
+ }
+ }
(None, Some(..), HalfOpen) => hir::LangItem::RangeTo,
- (Some(..), Some(..), HalfOpen) => hir::LangItem::Range,
+ (Some(..), Some(..), HalfOpen) => {
+ if self.tcx.features().new_range() {
+ hir::LangItem::RangeCopy
+ } else {
+ hir::LangItem::Range
+ }
+ }
(None, Some(..), Closed) => hir::LangItem::RangeToInclusive,
- (Some(..), Some(..), Closed) => unreachable!(),
+ (Some(e1), Some(e2), Closed) => {
+ if self.tcx.features().new_range() {
+ hir::LangItem::RangeInclusiveCopy
+ } else {
+ return self.lower_expr_range_closed(span, e1, e2);
+ }
+ }
(start, None, Closed) => {
self.dcx().emit_err(InclusiveRangeWithNoEnd { span });
match start {
- Some(..) => hir::LangItem::RangeFrom,
+ Some(..) => {
+ if self.tcx.features().new_range() {
+ hir::LangItem::RangeFromCopy
+ } else {
+ hir::LangItem::RangeFrom
+ }
+ }
None => hir::LangItem::RangeFull,
}
}
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 1a216ebf117c..7a30c8d4737b 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -568,6 +568,8 @@ declare_features! (
(unstable, never_type, "1.13.0", Some(35121)),
/// Allows diverging expressions to fall back to `!` rather than `()`.
(unstable, never_type_fallback, "1.41.0", Some(65992)),
+ /// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types.
+ (unstable, new_range, "CURRENT_RUSTC_VERSION", Some(123741)),
/// Allows `#![no_core]`.
(unstable, no_core, "1.3.0", Some(29639)),
/// Allows the use of `no_sanitize` attribute.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index af2f86b67e00..5483b97a7f4d 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2313,6 +2313,18 @@ impl Expr<'_> {
[val2],
StructTailExpr::None,
),
+ )
+ | (
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeFromCopy, _),
+ [val1],
+ StructTailExpr::None,
+ ),
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeFromCopy, _),
+ [val2],
+ StructTailExpr::None,
+ ),
) => val1.expr.equivalent_for_indexing(val2.expr),
(
ExprKind::Struct(
@@ -2325,6 +2337,30 @@ impl Expr<'_> {
[val2, val4],
StructTailExpr::None,
),
+ )
+ | (
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeCopy, _),
+ [val1, val3],
+ StructTailExpr::None,
+ ),
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeCopy, _),
+ [val2, val4],
+ StructTailExpr::None,
+ ),
+ )
+ | (
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeInclusiveCopy, _),
+ [val1, val3],
+ StructTailExpr::None,
+ ),
+ ExprKind::Struct(
+ QPath::LangItem(LangItem::RangeInclusiveCopy, _),
+ [val2, val4],
+ StructTailExpr::None,
+ ),
) => {
val1.expr.equivalent_for_indexing(val2.expr)
&& val3.expr.equivalent_for_indexing(val4.expr)
@@ -2354,7 +2390,10 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool {
| LangItem::RangeTo
| LangItem::RangeFrom
| LangItem::RangeFull
- | LangItem::RangeToInclusive,
+ | LangItem::RangeToInclusive
+ | LangItem::RangeCopy
+ | LangItem::RangeFromCopy
+ | LangItem::RangeInclusiveCopy,
..
)
),
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 02bc069fc5f2..3edf1370d2b4 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -415,6 +415,11 @@ language_item_table! {
RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
+ // `new_range` types that are `Copy + IntoIterator`
+ RangeFromCopy, sym::RangeFromCopy, range_from_copy_struct, Target::Struct, GenericRequirement::None;
+ RangeCopy, sym::RangeCopy, range_copy_struct, Target::Struct, GenericRequirement::None;
+ RangeInclusiveCopy, sym::RangeInclusiveCopy, range_inclusive_copy_struct, Target::Struct, GenericRequirement::None;
+
String, sym::String, string, Target::Struct, GenericRequirement::None;
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
}
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index e4a6a0fedc5a..fb48f5dca894 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2410,6 +2410,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let lang_item = match parent_expr.kind {
ExprKind::Struct(qpath, _, _) => match *qpath {
QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
+ QPath::LangItem(LangItem::RangeCopy, ..) => Some(LangItem::RangeCopy),
+ QPath::LangItem(LangItem::RangeInclusiveCopy, ..) => {
+ Some(LangItem::RangeInclusiveCopy)
+ }
QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
QPath::LangItem(LangItem::RangeToInclusive, ..) => {
Some(LangItem::RangeToInclusive)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6f1d3a74a816..dca96b74174d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -294,9 +294,12 @@ symbols! {
ProceduralMasqueradeDummyType,
Range,
RangeBounds,
+ RangeCopy,
RangeFrom,
+ RangeFromCopy,
RangeFull,
RangeInclusive,
+ RangeInclusiveCopy,
RangeTo,
RangeToInclusive,
Rc,
@@ -1367,6 +1370,7 @@ symbols! {
new_lower_hex,
new_octal,
new_pointer,
+ new_range,
new_unchecked,
new_upper_exp,
new_upper_hex,
diff --git a/library/core/src/range.rs b/library/core/src/range.rs
index 427526fd14b9..6a62928873fe 100644
--- a/library/core/src/range.rs
+++ b/library/core/src/range.rs
@@ -48,6 +48,7 @@ pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, Rang
/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
/// ```
+#[cfg_attr(not(bootstrap), lang = "RangeCopy")]
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct Range {
@@ -205,6 +206,7 @@ impl From> for Range {
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
/// ```
+#[cfg_attr(not(bootstrap), lang = "RangeInclusiveCopy")]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct RangeInclusive {
@@ -388,6 +390,7 @@ impl From> for RangeInclusive {
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
/// ```
+#[cfg_attr(not(bootstrap), lang = "RangeFromCopy")]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[unstable(feature = "new_range_api", issue = "125687")]
pub struct RangeFrom {
diff --git a/src/doc/unstable-book/src/language-features/new-range.md b/src/doc/unstable-book/src/language-features/new-range.md
new file mode 100644
index 000000000000..e7464f31e537
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/new-range.md
@@ -0,0 +1,9 @@
+# `new_range`
+
+The tracking issue for this feature is: [#123741]
+
+[#123741]: https://github.com/rust-lang/rust/issues/123741
+
+---
+
+Switch the syntaxes `a..`, `a..b`, and `a..=b` to resolve the new range types.
diff --git a/tests/ui/feature-gates/feature-gate-new_range.rs b/tests/ui/feature-gates/feature-gate-new_range.rs
new file mode 100644
index 000000000000..ecb73546d6a6
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-new_range.rs
@@ -0,0 +1,10 @@
+#![feature(new_range_api)]
+
+fn main() {
+ let a: core::range::RangeFrom = 1..;
+ //~^ mismatched types
+ let b: core::range::Range = 2..3;
+ //~^ mismatched types
+ let c: core::range::RangeInclusive = 4..=5;
+ //~^ mismatched types
+}
diff --git a/tests/ui/feature-gates/feature-gate-new_range.stderr b/tests/ui/feature-gates/feature-gate-new_range.stderr
new file mode 100644
index 000000000000..c4241390418b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-new_range.stderr
@@ -0,0 +1,48 @@
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:4:41
+ |
+LL | let a: core::range::RangeFrom = 1..;
+ | -------------------------- ^^^ expected `RangeFrom`, found `RangeFrom<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::RangeFrom`
+ found struct `std::ops::RangeFrom<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::RangeFrom<{integer}>` into `std::range::RangeFrom`
+ |
+LL | let a: core::range::RangeFrom = 1...into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:6:37
+ |
+LL | let b: core::range::Range = 2..3;
+ | ---------------------- ^^^^ expected `Range`, found `Range<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::Range`
+ found struct `std::ops::Range<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `std::range::Range`
+ |
+LL | let b: core::range::Range = 2..3.into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/feature-gate-new_range.rs:8:46
+ |
+LL | let c: core::range::RangeInclusive = 4..=5;
+ | ------------------------------- ^^^^^ expected `RangeInclusive`, found `RangeInclusive<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `std::range::RangeInclusive`
+ found struct `std::ops::RangeInclusive<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::RangeInclusive<{integer}>` into `std::range::RangeInclusive`
+ |
+LL | let c: core::range::RangeInclusive = 4..=5.into();
+ | +++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
index fc44c824043b..ba46a447802c 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed
@@ -9,5 +9,5 @@ fn main() {
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
- //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
}
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
index 973fe7ade602..b71613106199 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr
@@ -18,17 +18,17 @@ error[E0271]: expected `RangeInclusive<{integer}>` to be an iterator that yields
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
| ^^^^ expected `&&i32`, found integer
-error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+error[E0277]: expected a `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29
|
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+ | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(& as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
+ = help: the trait `for<'a> FnMut(&'a as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
= note: expected a closure with arguments `(&&&i32,)`
- found a closure with arguments `(& as Iterator>::Item,)`
+ found a closure with arguments `(& as Iterator>::Item,)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
index a96df10db355..0fd56707763e 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs
@@ -9,5 +9,5 @@ fn main() {
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
//[current]~^ ERROR type mismatch in closure arguments
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
- //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
+ //[next]~| ERROR expected a `FnMut(& as Iterator>::Item)` closure, found
}
diff --git a/tests/ui/new-range/disabled.rs b/tests/ui/new-range/disabled.rs
new file mode 100644
index 000000000000..1a5fe3f97436
--- /dev/null
+++ b/tests/ui/new-range/disabled.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(new_range_api)]
+
+fn main() {
+ // Unchanged
+ let a: core::range::RangeFull = ..;
+ let b: core::range::RangeTo = ..2;
+ let c: core::range::RangeToInclusive = ..=3;
+
+ let _: core::ops::RangeFull = a;
+ let _: core::ops::RangeTo = b;
+ let _: core::ops::RangeToInclusive = c;
+
+ // Changed
+ let a: core::range::legacy::RangeFrom = 1..;
+ let b: core::range::legacy::Range = 2..3;
+ let c: core::range::legacy::RangeInclusive = 4..=5;
+
+ let a: core::ops::RangeFrom = a;
+ let b: core::ops::Range = b;
+ let c: core::ops::RangeInclusive = c;
+
+ let _: core::ops::RangeFrom = a.into_iter();
+ let _: core::ops::Range = b.into_iter();
+ let _: core::ops::RangeInclusive = c.into_iter();
+}
diff --git a/tests/ui/new-range/enabled.rs b/tests/ui/new-range/enabled.rs
new file mode 100644
index 000000000000..a5fb76ad52b7
--- /dev/null
+++ b/tests/ui/new-range/enabled.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+#![feature(new_range_api)]
+#![feature(new_range)]
+
+fn main() {
+ // Unchanged
+ let a: core::range::RangeFull = ..;
+ let b: core::range::RangeTo = ..2;
+ let c: core::range::RangeToInclusive = ..=3;
+
+ let _: core::ops::RangeFull = a;
+ let _: core::ops::RangeTo = b;
+ let _: core::ops::RangeToInclusive = c;
+
+ // Changed
+ let a: core::range::RangeFrom = 1..;
+ let b: core::range::Range = 2..3;
+ let c: core::range::RangeInclusive = 4..=5;
+
+ let _: core::range::IterRangeFrom = a.into_iter();
+ let _: core::range::IterRange = b.into_iter();
+ let _: core::range::IterRangeInclusive = c.into_iter();
+}
From 88260f4ba4b0b9f86094bd1b2495c027bf959dbe Mon Sep 17 00:00:00 2001
From: Jorge Aparicio
Date: Tue, 21 Jan 2025 18:00:04 +0100
Subject: [PATCH 23/68] 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 fd9bf47234c6..ba8f2cc618d7 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 cf55fff4078a..370673dfca15 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 b5310108dbf7..40c995895434 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 f23025305f88cf4d822452960dd707d5abee555f Mon Sep 17 00:00:00 2001
From: Scott McMurray
Date: Sun, 19 Jan 2025 23:38:09 -0800
Subject: [PATCH 24/68] Add `unchecked_disjoint_bitor` with fallback intrinsic
implementation
---
.../rustc_hir_analysis/src/check/intrinsic.rs | 2 +-
compiler/rustc_span/src/symbol.rs | 1 +
library/core/src/intrinsics/fallback.rs | 40 +++++++++++++
library/core/src/intrinsics/mod.rs | 19 ++++++
library/core/src/lib.rs | 1 +
library/core/src/num/uint_macros.rs | 59 ++++++++++++++++++-
6 files changed, 118 insertions(+), 4 deletions(-)
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index cf3d48973042..c3404fa1624b 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -472,7 +472,7 @@ pub fn check_intrinsic_type(
vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
tcx.types.usize,
),
- sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
+ sym::unchecked_div | sym::unchecked_rem | sym::exact_div | sym::disjoint_bitor => {
(1, 0, vec![param(0), param(0)], param(0))
}
sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7f7b460cf570..e9e62655bb73 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -776,6 +776,7 @@ symbols! {
discriminant_kind,
discriminant_type,
discriminant_value,
+ disjoint_bitor,
dispatch_from_dyn,
div,
div_assign,
diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs
index 70484e4d0f2a..dca211eba80e 100644
--- a/library/core/src/intrinsics/fallback.rs
+++ b/library/core/src/intrinsics/fallback.rs
@@ -110,3 +110,43 @@ impl const CarryingMulAdd for i128 {
(low, high)
}
}
+
+#[const_trait]
+#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
+pub trait DisjointBitOr: Copy + 'static {
+ /// This is always just `assume((self & other) == 0); self | other`.
+ ///
+ /// It's essential that the assume is there so that this is sufficient to
+ /// specify the UB for MIRI, rather than it needing to re-implement it.
+ ///
+ /// # Safety
+ /// See [`super::disjoint_bitor`].
+ unsafe fn disjoint_bitor(self, other: Self) -> Self;
+}
+macro_rules! zero {
+ (bool) => {
+ false
+ };
+ ($t:ident) => {
+ 0
+ };
+}
+macro_rules! impl_disjoint_bitor {
+ ($($t:ident,)+) => {$(
+ #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
+ impl const DisjointBitOr for $t {
+ #[inline]
+ unsafe fn disjoint_bitor(self, other: Self) -> Self {
+ // SAFETY: our precondition is that there are no bits in common,
+ // so this is just telling that to the backend.
+ unsafe { super::assume((self & other) == zero!($t)) };
+ self | other
+ }
+ }
+ )+};
+}
+impl_disjoint_bitor! {
+ bool,
+ u8, u16, u32, u64, u128, usize,
+ i8, i16, i32, i64, i128, isize,
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index c0d435f99c0c..37d9b5223143 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3244,6 +3244,25 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi
unimplemented!()
}
+/// Combine two values which have no bits in common.
+///
+/// This allows the backend to implement it as `a + b` *or* `a | b`,
+/// depending which us easier to implement on a specific target.
+///
+/// # Safety
+///
+/// Requires that `(a & b) == 0`, or equivalently that `(a | b) == (a + b)`.
+///
+/// Otherwise it's immediate UB.
+#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
+#[rustc_nounwind]
+#[cfg_attr(not(bootstrap), rustc_intrinsic)]
+#[miri::intrinsic_fallback_is_spec] // the fallbacks all `assume` to tell MIRI
+pub const unsafe fn disjoint_bitor(a: T, b: T) -> T {
+ // SAFETY: same preconditions as this function.
+ unsafe { fallback::DisjointBitOr::disjoint_bitor(a, b) }
+}
+
/// Performs checked integer addition.
///
/// Note that, unlike most intrinsics, this is safe to call;
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index c18e0405f729..b9471f169797 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -117,6 +117,7 @@
#![feature(const_eval_select)]
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
+#![feature(disjoint_bitor)]
#![feature(internal_impls_macro)]
#![feature(ip)]
#![feature(is_ascii_octdigit)]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c8433b3bb168..c909ab56ac83 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1187,6 +1187,52 @@ macro_rules! uint_impl {
self % rhs
}
+ /// Same value as
+ #[doc = concat!("`<", stringify!($SelfT), " as BitOr>::bitor(self, other)`")]
+ /// but UB if any bit position is set in both inputs.
+ ///
+ /// This is a situational μoptimization for places where you'd rather use
+ /// addition on some platforms and bitwise or on other platforms, based on
+ /// exactly which instructions combine better with whatever else you're
+ /// doing. Note that there's no reason to bother using this for places
+ /// where it's clear from the operations involved that they can't overlap.
+ /// For example, if you're combining `u16`s into a `u32` with
+ /// `((a as u32) << 16) | (b as u32)`, that's fine, as the backend will
+ /// know those sides of the `|` are disjoint without needing help.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(disjoint_bitor)]
+ ///
+ /// // SAFETY: `1` and `4` have no bits in common.
+ /// unsafe {
+ #[doc = concat!(" assert_eq!(1_", stringify!($SelfT), ".unchecked_disjoint_bitor(4), 5);")]
+ /// }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// Requires that `(self | other) == 0`, otherwise it's immediate UB.
+ ///
+ /// Equivalently, requires that `(self | other) == (self + other)`.
+ #[unstable(feature = "disjoint_bitor", issue = "135758")]
+ #[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
+ #[inline]
+ pub const unsafe fn unchecked_disjoint_bitor(self, other: Self) -> Self {
+ assert_unsafe_precondition!(
+ check_language_ub,
+ concat!(stringify!($SelfT), "::unchecked_disjoint_bitor cannot have overlapping bits"),
+ (
+ lhs: $SelfT = self,
+ rhs: $SelfT = other,
+ ) => (lhs & rhs) == 0,
+ );
+
+ // SAFETY: Same precondition
+ unsafe { intrinsics::disjoint_bitor(self, other) }
+ }
+
/// Returns the logarithm of the number with respect to an arbitrary base,
/// rounded down.
///
@@ -2346,15 +2392,22 @@ macro_rules! uint_impl {
/// assert_eq!((sum1, sum0), (9, 6));
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
+ #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
// note: longer-term this should be done via an intrinsic, but this has been shown
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
- let (a, b) = self.overflowing_add(rhs);
- let (c, d) = a.overflowing_add(carry as $SelfT);
- (c, b | d)
+ let (a, c1) = self.overflowing_add(rhs);
+ let (b, c2) = a.overflowing_add(carry as $SelfT);
+ // Ideally LLVM would know this is disjoint without us telling them,
+ // but it doesn't
+ // SAFETY: Only one of `c1` and `c2` can be set.
+ // For c1 to be set we need to have overflowed, but if we did then
+ // `a` is at most `MAX-1`, which means that `c2` cannot possibly
+ // overflow because it's adding at most `1` (since it came from `bool`)
+ (b, unsafe { intrinsics::disjoint_bitor(c1, c2) })
}
/// Calculates `self` + `rhs` with a signed `rhs`.
From 4ee1602eab2cdc88172d4a98f927613ab64b4cf0 Mon Sep 17 00:00:00 2001
From: Scott McMurray
Date: Mon, 20 Jan 2025 00:00:44 -0800
Subject: [PATCH 25/68] Override `disjoint_or` in the LLVM backend
---
compiler/rustc_codegen_llvm/src/builder.rs | 8 ++++++++
compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 +++
.../rustc_codegen_ssa/src/mir/intrinsic.rs | 5 +++++
.../rustc_codegen_ssa/src/traits/builder.rs | 5 +++++
tests/codegen/bigint-helpers.rs | 13 ++++++++++++
tests/codegen/intrinsics/disjoint_bitor.rs | 20 +++++++++++++++++++
6 files changed, 54 insertions(+)
create mode 100644 tests/codegen/bigint-helpers.rs
create mode 100644 tests/codegen/intrinsics/disjoint_bitor.rs
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 2d007416263f..6e1eec4f0fc9 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -421,6 +421,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
unchecked_umul(x, y) => LLVMBuildNUWMul,
}
+ fn or_disjoint(&mut self, a: &'ll Value, b: &'ll Value) -> &'ll Value {
+ unsafe {
+ let or = llvm::LLVMBuildOr(self.llbuilder, a, b, UNNAMED);
+ llvm::LLVMSetIsDisjoint(or, True);
+ or
+ }
+ }
+
set_math_builder_methods! {
fadd_fast(x, y) => (LLVMBuildFAdd, LLVMRustSetFastMath),
fsub_fast(x, y) => (LLVMBuildFSub, LLVMRustSetFastMath),
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index cc7c5231aca5..8d494b0fe621 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1380,6 +1380,9 @@ unsafe extern "C" {
pub fn LLVMBuildFNeg<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
pub fn LLVMBuildNot<'a>(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value;
+ // Extra flags on arithmetic
+ pub fn LLVMSetIsDisjoint(Instr: &Value, IsDisjoint: Bool);
+
// Memory
pub fn LLVMBuildAlloca<'a>(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value;
pub fn LLVMBuildArrayAlloca<'a>(
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 304ac4544ee4..6e7fbe62c8df 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -225,6 +225,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
args[1].val.unaligned_volatile_store(bx, dst);
return Ok(());
}
+ sym::disjoint_bitor => {
+ let a = args[0].immediate();
+ let b = args[1].immediate();
+ bx.or_disjoint(a, b)
+ }
sym::exact_div => {
let ty = arg_tys[0];
match int_type_width_signed(ty, bx.tcx()) {
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index bbf87a599426..b7dcf16fa2bc 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -167,6 +167,11 @@ pub trait BuilderMethods<'a, 'tcx>:
fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+ /// Defaults to [`Self::or`], but guarantees `(lhs & rhs) == 0` so some backends
+ /// can emit something more helpful for optimizations.
+ fn or_disjoint(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
+ self.or(lhs, rhs)
+ }
fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
fn neg(&mut self, v: Self::Value) -> Self::Value;
fn fneg(&mut self, v: Self::Value) -> Self::Value;
diff --git a/tests/codegen/bigint-helpers.rs b/tests/codegen/bigint-helpers.rs
new file mode 100644
index 000000000000..355cccb81504
--- /dev/null
+++ b/tests/codegen/bigint-helpers.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -C opt-level=3
+
+#![crate_type = "lib"]
+#![feature(bigint_helper_methods)]
+
+// CHECK-LABEL: @u32_carrying_add
+#[no_mangle]
+pub fn u32_carrying_add(a: u32, b: u32, c: bool) -> (u32, bool) {
+ // CHECK: @llvm.uadd.with.overflow.i32
+ // CHECK: @llvm.uadd.with.overflow.i32
+ // CHECK: or disjoint i1
+ u32::carrying_add(a, b, c)
+}
diff --git a/tests/codegen/intrinsics/disjoint_bitor.rs b/tests/codegen/intrinsics/disjoint_bitor.rs
new file mode 100644
index 000000000000..be9954507b3f
--- /dev/null
+++ b/tests/codegen/intrinsics/disjoint_bitor.rs
@@ -0,0 +1,20 @@
+//@ compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::disjoint_bitor;
+
+// CHECK-LABEL: @disjoint_bitor_signed
+#[no_mangle]
+pub unsafe fn disjoint_bitor_signed(x: i32, y: i32) -> i32 {
+ // CHECK: or disjoint i32 %x, %y
+ disjoint_bitor(x, y)
+}
+
+// CHECK-LABEL: @disjoint_bitor_unsigned
+#[no_mangle]
+pub unsafe fn disjoint_bitor_unsigned(x: u64, y: u64) -> u64 {
+ // CHECK: or disjoint i64 %x, %y
+ disjoint_bitor(x, y)
+}
From 61150a80f5d4fffea74ee9dabc991219813c744e Mon Sep 17 00:00:00 2001
From: Scott McMurray
Date: Wed, 22 Jan 2025 01:00:59 -0800
Subject: [PATCH 26/68] PR feedback
---
library/core/src/intrinsics/fallback.rs | 12 +++++-------
library/core/src/intrinsics/mod.rs | 3 ++-
library/core/src/num/uint_macros.rs | 2 +-
.../miri/tests/fail/intrinsics/disjoint_bitor.rs | 5 +++++
.../tests/fail/intrinsics/disjoint_bitor.stderr | 15 +++++++++++++++
5 files changed, 28 insertions(+), 9 deletions(-)
create mode 100644 src/tools/miri/tests/fail/intrinsics/disjoint_bitor.rs
create mode 100644 src/tools/miri/tests/fail/intrinsics/disjoint_bitor.stderr
diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs
index dca211eba80e..eec5c4d646d0 100644
--- a/library/core/src/intrinsics/fallback.rs
+++ b/library/core/src/intrinsics/fallback.rs
@@ -114,13 +114,8 @@ impl const CarryingMulAdd for i128 {
#[const_trait]
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
pub trait DisjointBitOr: Copy + 'static {
- /// This is always just `assume((self & other) == 0); self | other`.
- ///
- /// It's essential that the assume is there so that this is sufficient to
- /// specify the UB for MIRI, rather than it needing to re-implement it.
- ///
- /// # Safety
- /// See [`super::disjoint_bitor`].
+ /// See [`super::disjoint_bitor`]; we just need the trait indirection to handle
+ /// different types since calling intrinsics with generics doesn't work.
unsafe fn disjoint_bitor(self, other: Self) -> Self;
}
macro_rules! zero {
@@ -135,8 +130,11 @@ macro_rules! impl_disjoint_bitor {
($($t:ident,)+) => {$(
#[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")]
impl const DisjointBitOr for $t {
+ #[cfg_attr(miri, track_caller)]
#[inline]
unsafe fn disjoint_bitor(self, other: Self) -> Self {
+ // Note that the assume here is required for UB detection in Miri!
+
// SAFETY: our precondition is that there are no bits in common,
// so this is just telling that to the backend.
unsafe { super::assume((self & other) == zero!($t)) };
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 37d9b5223143..c505eb95013a 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3257,7 +3257,8 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi
#[rustc_const_unstable(feature = "disjoint_bitor", issue = "135758")]
#[rustc_nounwind]
#[cfg_attr(not(bootstrap), rustc_intrinsic)]
-#[miri::intrinsic_fallback_is_spec] // the fallbacks all `assume` to tell MIRI
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[miri::intrinsic_fallback_is_spec] // the fallbacks all `assume` to tell Miri
pub const unsafe fn disjoint_bitor(a: T, b: T) -> T {
// SAFETY: same preconditions as this function.
unsafe { fallback::DisjointBitOr::disjoint_bitor(a, b) }
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index c909ab56ac83..f2d41fd93d5c 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1213,7 +1213,7 @@ macro_rules! uint_impl {
///
/// # Safety
///
- /// Requires that `(self | other) == 0`, otherwise it's immediate UB.
+ /// Requires that `(self & other) == 0`, otherwise it's immediate UB.
///
/// Equivalently, requires that `(self | other) == (self + other)`.
#[unstable(feature = "disjoint_bitor", issue = "135758")]
diff --git a/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.rs b/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.rs
new file mode 100644
index 000000000000..a71271433308
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.rs
@@ -0,0 +1,5 @@
+#![feature(core_intrinsics)]
+fn main() {
+ // one bit in common
+ unsafe { std::intrinsics::disjoint_bitor(0b01101001_u8, 0b10001110) }; //~ ERROR: Undefined Behavior
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.stderr b/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.stderr
new file mode 100644
index 000000000000..82502953118a
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/disjoint_bitor.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `assume` called with `false`
+ --> tests/fail/intrinsics/disjoint_bitor.rs:LL:CC
+ |
+LL | unsafe { std::intrinsics::disjoint_bitor(0b01101001_u8, 0b10001110) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `assume` called with `false`
+ |
+ = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+ = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+ = note: BACKTRACE:
+ = note: inside `main` at tests/fail/intrinsics/disjoint_bitor.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
From 5e6ae8bb5c884deea85c6f18cfba79fe48ccafa0 Mon Sep 17 00:00:00 2001
From: Scott McMurray
Date: Fri, 31 Jan 2025 22:31:43 -0800
Subject: [PATCH 27/68] More PR feedback
---
library/core/src/intrinsics/mod.rs | 2 +-
library/core/src/num/uint_macros.rs | 10 ++++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index c505eb95013a..8db390622bad 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -3247,7 +3247,7 @@ pub const fn three_way_compare(_lhs: T, _rhss: T) -> crate::cmp::Orderi
/// Combine two values which have no bits in common.
///
/// This allows the backend to implement it as `a + b` *or* `a | b`,
-/// depending which us easier to implement on a specific target.
+/// depending which is easier to implement on a specific target.
///
/// # Safety
///
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index f2d41fd93d5c..29f6791ee6ad 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1187,13 +1187,11 @@ macro_rules! uint_impl {
self % rhs
}
- /// Same value as
- #[doc = concat!("`<", stringify!($SelfT), " as BitOr>::bitor(self, other)`")]
- /// but UB if any bit position is set in both inputs.
+ /// Same value as `self | other`, but UB if any bit position is set in both inputs.
///
- /// This is a situational μoptimization for places where you'd rather use
- /// addition on some platforms and bitwise or on other platforms, based on
- /// exactly which instructions combine better with whatever else you're
+ /// This is a situational micro-optimization for places where you'd rather
+ /// use addition on some platforms and bitwise or on other platforms, based
+ /// on exactly which instructions combine better with whatever else you're
/// doing. Note that there's no reason to bother using this for places
/// where it's clear from the operations involved that they can't overlap.
/// For example, if you're combining `u16`s into a `u32` with
From 670d892dc9f1b6f74b7103a6602262f383197d20 Mon Sep 17 00:00:00 2001
From: Peter Jaszkowiak
Date: Sat, 1 Feb 2025 13:09:28 -0700
Subject: [PATCH 28/68] add UnsafeCell direct access APIs
---
library/core/src/cell.rs | 84 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 20187e478aac..320d8176011f 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2118,6 +2118,35 @@ impl UnsafeCell {
pub const fn into_inner(self) -> T {
self.value
}
+
+ /// Replace the value in this `UnsafeCell` and return the old value.
+ ///
+ /// # Safety
+ ///
+ /// The caller must take care to avoid aliasing and data races.
+ ///
+ /// - It is Undefined Behavior to allow calls to race with
+ /// any other access to the wrapped value.
+ /// - It is Undefined Behavior to call this while any other
+ /// reference(s) to the wrapped value are alive.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unsafe_cell_access)]
+ /// use std::cell::UnsafeCell;
+ ///
+ /// let uc = UnsafeCell::new(5);
+ ///
+ /// let old = unsafe { uc.replace(10) };
+ /// assert_eq!(old, 5);
+ /// ```
+ #[inline]
+ #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+ pub const unsafe fn replace(&self, value: T) -> T {
+ // SAFETY: pointer comes from `&self` so naturally satisfies invariants.
+ unsafe { ptr::replace(self.get(), value) }
+ }
}
impl UnsafeCell {
@@ -2230,6 +2259,61 @@ impl UnsafeCell {
// no guarantee for user code that this will work in future versions of the compiler!
this as *const T as *mut T
}
+
+ /// Get a shared reference to the value within the `UnsafeCell`.
+ ///
+ /// # Safety
+ ///
+ /// - It is Undefined Behavior to call this while any mutable
+ /// reference to the wrapped value is alive.
+ /// - Mutating the wrapped value while the returned
+ /// reference is alive is Undefined Behavior.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unsafe_cell_access)]
+ /// use std::cell::UnsafeCell;
+ ///
+ /// let uc = UnsafeCell::new(5);
+ ///
+ /// let val = unsafe { uc.as_ref_unchecked() };
+ /// assert_eq!(val, &5);
+ /// ```
+ #[inline]
+ #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+ pub const unsafe fn as_ref_unchecked(&self) -> &T {
+ // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
+ unsafe { self.get().as_ref_unchecked() }
+ }
+
+ /// Get an exclusive reference to the value within the `UnsafeCell`.
+ ///
+ /// # Safety
+ ///
+ /// - It is Undefined Behavior to call this while any other
+ /// reference(s) to the wrapped value are alive.
+ /// - Mutating the wrapped value through other means while the
+ /// returned reference is alive is Undefined Behavior.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(unsafe_cell_access)]
+ /// use std::cell::UnsafeCell;
+ ///
+ /// let uc = UnsafeCell::new(5);
+ ///
+ /// unsafe { *uc.as_mut_unchecked() += 1; }
+ /// assert_eq!(uc.into_inner(), 6);
+ /// ```
+ #[inline]
+ #[unstable(feature = "unsafe_cell_access", issue = "136327")]
+ #[allow(clippy::mut_from_ref)]
+ pub const unsafe fn as_mut_unchecked(&self) -> &mut T {
+ // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants.
+ unsafe { self.get().as_mut_unchecked() }
+ }
}
#[stable(feature = "unsafe_cell_default", since = "1.10.0")]
From 7f1231c986c26dcd1b519b81b78371a750db797a Mon Sep 17 00:00:00 2001
From: Mark Rousskov
Date: Sun, 26 Jan 2025 20:47:49 -0500
Subject: [PATCH 29/68] Shard AllocMap Lock
This improves performance on many-seed parallel (-Zthreads=32) miri
executions from managing to use ~8 cores to using 27-28 cores. That's
pretty reasonable scaling for the simplicity of this solution.
---
.../rustc_middle/src/mir/interpret/mod.rs | 66 ++++++++++++-------
compiler/rustc_middle/src/ty/context.rs | 4 +-
2 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index f4f9f221a751..45c862e0d34b 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -15,7 +15,8 @@ use std::{fmt, io};
use rustc_abi::{AddressSpace, Align, Endian, HasDataLayout, Size};
use rustc_ast::{LitKind, Mutability};
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::sharded::ShardedHashMap;
+use rustc_data_structures::sync::{AtomicU64, Lock};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
@@ -389,35 +390,39 @@ pub const CTFE_ALLOC_SALT: usize = 0;
pub(crate) struct AllocMap<'tcx> {
/// Maps `AllocId`s to their corresponding allocations.
- alloc_map: FxHashMap>,
+ // Note that this map on rustc workloads seems to be rather dense, but in miri workloads should
+ // be pretty sparse. In #136105 we considered replacing it with a (dense) Vec-based map, but
+ // since there are workloads where it can be sparse we decided to go with sharding for now. At
+ // least up to 32 cores the one workload tested didn't exhibit much difference between the two.
+ //
+ // Should be locked *after* locking dedup if locking both to avoid deadlocks.
+ to_alloc: ShardedHashMap>,
/// Used to deduplicate global allocations: functions, vtables, string literals, ...
///
/// The `usize` is a "salt" used by Miri to make deduplication imperfect, thus better emulating
/// the actual guarantees.
- dedup: FxHashMap<(GlobalAlloc<'tcx>, usize), AllocId>,
+ dedup: Lock, usize), AllocId>>,
/// The `AllocId` to assign to the next requested ID.
/// Always incremented; never gets smaller.
- next_id: AllocId,
+ next_id: AtomicU64,
}
impl<'tcx> AllocMap<'tcx> {
pub(crate) fn new() -> Self {
AllocMap {
- alloc_map: Default::default(),
+ to_alloc: Default::default(),
dedup: Default::default(),
- next_id: AllocId(NonZero::new(1).unwrap()),
+ next_id: AtomicU64::new(1),
}
}
- fn reserve(&mut self) -> AllocId {
- let next = self.next_id;
- self.next_id.0 = self.next_id.0.checked_add(1).expect(
- "You overflowed a u64 by incrementing by 1... \
- You've just earned yourself a free drink if we ever meet. \
- Seriously, how did you do that?!",
- );
- next
+ fn reserve(&self) -> AllocId {
+ // Technically there is a window here where we overflow and then another thread
+ // increments `next_id` *again* and uses it before we panic and tear down the entire session.
+ // We consider this fine since such overflows cannot realistically occur.
+ let next_id = self.next_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
+ AllocId(NonZero::new(next_id).unwrap())
}
}
@@ -428,26 +433,34 @@ impl<'tcx> TyCtxt<'tcx> {
/// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
/// an `AllocId` from a query.
pub fn reserve_alloc_id(self) -> AllocId {
- self.alloc_map.lock().reserve()
+ self.alloc_map.reserve()
}
/// Reserves a new ID *if* this allocation has not been dedup-reserved before.
/// Should not be used for mutable memory.
fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>, salt: usize) -> AllocId {
- let mut alloc_map = self.alloc_map.lock();
if let GlobalAlloc::Memory(mem) = alloc {
if mem.inner().mutability.is_mut() {
bug!("trying to dedup-reserve mutable memory");
}
}
let alloc_salt = (alloc, salt);
- if let Some(&alloc_id) = alloc_map.dedup.get(&alloc_salt) {
+ // Locking this *before* `to_alloc` also to ensure correct lock order.
+ let mut dedup = self.alloc_map.dedup.lock();
+ if let Some(&alloc_id) = dedup.get(&alloc_salt) {
return alloc_id;
}
- let id = alloc_map.reserve();
+ let id = self.alloc_map.reserve();
debug!("creating alloc {:?} with id {id:?}", alloc_salt.0);
- alloc_map.alloc_map.insert(id, alloc_salt.0.clone());
- alloc_map.dedup.insert(alloc_salt, id);
+ let had_previous = self
+ .alloc_map
+ .to_alloc
+ .lock_shard_by_value(&id)
+ .insert(id, alloc_salt.0.clone())
+ .is_some();
+ // We just reserved, so should always be unique.
+ assert!(!had_previous);
+ dedup.insert(alloc_salt, id);
id
}
@@ -497,7 +510,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// local dangling pointers and allocations in constants/statics.
#[inline]
pub fn try_get_global_alloc(self, id: AllocId) -> Option> {
- self.alloc_map.lock().alloc_map.get(&id).cloned()
+ self.alloc_map.to_alloc.lock_shard_by_value(&id).get(&id).cloned()
}
#[inline]
@@ -516,7 +529,9 @@ impl<'tcx> TyCtxt<'tcx> {
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
/// call this function twice, even with the same `Allocation` will ICE the compiler.
pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
- if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
+ if let Some(old) =
+ self.alloc_map.to_alloc.lock_shard_by_value(&id).insert(id, GlobalAlloc::Memory(mem))
+ {
bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
}
}
@@ -524,8 +539,11 @@ impl<'tcx> TyCtxt<'tcx> {
/// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to
/// call this function twice, even with the same `DefId` will ICE the compiler.
pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) {
- if let Some(old) =
- self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Static(def_id.to_def_id()))
+ if let Some(old) = self
+ .alloc_map
+ .to_alloc
+ .lock_shard_by_value(&id)
+ .insert(id, GlobalAlloc::Static(def_id.to_def_id()))
{
bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
}
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 69f6fc0ad8a6..0f1fc891b0f9 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1366,7 +1366,7 @@ pub struct GlobalCtxt<'tcx> {
pub data_layout: TargetDataLayout,
/// Stores memory for globals (statics/consts).
- pub(crate) alloc_map: Lock>,
+ pub(crate) alloc_map: interpret::AllocMap<'tcx>,
current_gcx: CurrentGcx,
}
@@ -1583,7 +1583,7 @@ impl<'tcx> TyCtxt<'tcx> {
new_solver_evaluation_cache: Default::default(),
canonical_param_env_cache: Default::default(),
data_layout,
- alloc_map: Lock::new(interpret::AllocMap::new()),
+ alloc_map: interpret::AllocMap::new(),
current_gcx,
});
From 0878692e0d4ea9e2ad39d37a1c70e5bf4bf563e4 Mon Sep 17 00:00:00 2001
From: vayunbiyani
Date: Tue, 21 Jan 2025 15:06:52 -0500
Subject: [PATCH 30/68] Ported tests/ui/simd to use the intrinsic macro
---
tests/ui/simd/array-trait.rs | 10 +--
tests/ui/simd/array-type.rs | 10 +--
tests/ui/simd/generics.rs | 5 +-
tests/ui/simd/intrinsic/float-math-pass.rs | 72 +++++++++++++------
.../ui/simd/intrinsic/generic-arithmetic-2.rs | 65 ++++++++++++-----
.../intrinsic/generic-arithmetic-2.stderr | 48 ++++++-------
.../simd/intrinsic/generic-arithmetic-pass.rs | 65 ++++++++++++-----
.../generic-arithmetic-saturating-2.rs | 10 +--
.../generic-arithmetic-saturating-2.stderr | 4 +-
.../generic-arithmetic-saturating-pass.rs | 10 +--
tests/ui/simd/intrinsic/generic-as.rs | 6 +-
.../ui/simd/intrinsic/generic-bitmask-pass.rs | 5 +-
tests/ui/simd/intrinsic/generic-bitmask.rs | 5 +-
.../ui/simd/intrinsic/generic-bitmask.stderr | 10 +--
tests/ui/simd/intrinsic/generic-bswap-byte.rs | 5 +-
tests/ui/simd/intrinsic/generic-cast-pass.rs | 6 +-
.../intrinsic/generic-cast-pointer-width.rs | 5 +-
tests/ui/simd/intrinsic/generic-cast.rs | 5 +-
tests/ui/simd/intrinsic/generic-cast.stderr | 8 +--
.../simd/intrinsic/generic-comparison-pass.rs | 26 ++++---
tests/ui/simd/intrinsic/generic-comparison.rs | 26 ++++---
.../simd/intrinsic/generic-comparison.stderr | 36 +++++-----
.../simd/intrinsic/generic-elements-pass.rs | 13 ++--
tests/ui/simd/intrinsic/generic-elements.rs | 19 +++--
.../ui/simd/intrinsic/generic-elements.stderr | 42 +++++------
.../ui/simd/intrinsic/generic-gather-pass.rs | 9 +--
.../simd/intrinsic/generic-reduction-pass.rs | 45 ++++++++----
tests/ui/simd/intrinsic/generic-reduction.rs | 28 +++++---
.../simd/intrinsic/generic-reduction.stderr | 20 +++---
.../ui/simd/intrinsic/generic-select-pass.rs | 10 +--
tests/ui/simd/intrinsic/generic-select.rs | 11 +--
tests/ui/simd/intrinsic/generic-select.stderr | 16 ++---
tests/ui/simd/intrinsic/generic-shuffle.rs | 6 +-
.../simd/intrinsic/inlining-issue67557-ice.rs | 5 +-
.../ui/simd/intrinsic/inlining-issue67557.rs | 5 +-
tests/ui/simd/intrinsic/issue-85855.rs | 21 +++---
tests/ui/simd/intrinsic/issue-85855.stderr | 18 ++---
tests/ui/simd/intrinsic/ptr-cast.rs | 14 ++--
tests/ui/simd/issue-105439.rs | 5 +-
tests/ui/simd/issue-39720.rs | 5 +-
tests/ui/simd/issue-85915-simd-ptrs.rs | 10 +--
tests/ui/simd/issue-89193.rs | 5 +-
tests/ui/simd/masked-load-store-build-fail.rs | 10 +--
.../simd/masked-load-store-build-fail.stderr | 16 ++---
tests/ui/simd/masked-load-store-check-fail.rs | 9 +--
.../simd/masked-load-store-check-fail.stderr | 20 +++---
tests/ui/simd/masked-load-store.rs | 9 +--
.../monomorphize-shuffle-index.generic.stderr | 2 +-
tests/ui/simd/monomorphize-shuffle-index.rs | 15 ++--
tests/ui/simd/repr_packed.rs | 5 +-
tests/ui/simd/shuffle.rs | 5 +-
tests/ui/simd/simd-bitmask-notpow2.rs | 10 +--
tests/ui/simd/simd-bitmask.rs | 10 +--
53 files changed, 515 insertions(+), 345 deletions(-)
diff --git a/tests/ui/simd/array-trait.rs b/tests/ui/simd/array-trait.rs
index 67583bf82087..32cbf01428ca 100644
--- a/tests/ui/simd/array-trait.rs
+++ b/tests/ui/simd/array-trait.rs
@@ -24,10 +24,12 @@ pub struct T([S::Lane; S::SIZE]);
//~| ERROR SIMD vector element type should be a primitive scalar
//~| ERROR unconstrained generic constant
-extern "rust-intrinsic" {
- fn simd_insert(x: T, idx: u32, y: E) -> T;
- fn simd_extract(x: T, idx: u32) -> E;
-}
+#[rustc_intrinsic]
+unsafe fn simd_insert(x: T, idx: u32, y: E) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_extract(x: T, idx: u32) -> E;
+
pub fn main() {
let mut t = T::([0; 4]);
diff --git a/tests/ui/simd/array-type.rs b/tests/ui/simd/array-type.rs
index 8ca53b1a453f..d1de70044169 100644
--- a/tests/ui/simd/array-type.rs
+++ b/tests/ui/simd/array-type.rs
@@ -12,10 +12,12 @@ struct S([i32; 4]);
#[derive(Copy, Clone)]
struct T([i32; N]);
-extern "rust-intrinsic" {
- fn simd_insert(x: T, idx: u32, y: E) -> T;
- fn simd_extract(x: T, idx: u32) -> E;
-}
+#[rustc_intrinsic]
+unsafe fn simd_insert(x: T, idx: u32, y: E) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_extract(x: T, idx: u32) -> E;
+
pub fn main() {
let mut s = S([0; 4]);
diff --git a/tests/ui/simd/generics.rs b/tests/ui/simd/generics.rs
index f96a7cd75e93..453ed86c14a9 100644
--- a/tests/ui/simd/generics.rs
+++ b/tests/ui/simd/generics.rs
@@ -21,9 +21,8 @@ struct B([T; 4]);
struct C([T; N]);
-extern "rust-intrinsic" {
- fn simd_add(x: T, y: T) -> T;
-}
+#[rustc_intrinsic]
+unsafe fn simd_add(x: T, y: T) -> T;
fn add>(lhs: T, rhs: T) -> T {
lhs + rhs
diff --git a/tests/ui/simd/intrinsic/float-math-pass.rs b/tests/ui/simd/intrinsic/float-math-pass.rs
index 24b9941133ee..74cb51a06068 100644
--- a/tests/ui/simd/intrinsic/float-math-pass.rs
+++ b/tests/ui/simd/intrinsic/float-math-pass.rs
@@ -15,27 +15,59 @@
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub [f32; 4]);
-extern "rust-intrinsic" {
- fn simd_fsqrt(x: T) -> T;
- fn simd_fabs(x: T) -> T;
- fn simd_fsin(x: T) -> T;
- fn simd_fcos(x: T) -> T;
- fn simd_fexp(x: T) -> T;
- fn simd_fexp2(x: T) -> T;
- fn simd_fma(x: T, y: T, z: T) -> T;
- fn simd_relaxed_fma(x: T, y: T, z: T) -> T;
- fn simd_flog(x: T) -> T;
- fn simd_flog10(x: T) -> T;
- fn simd_flog2(x: T) -> T;
- fn simd_fpow(x: T, y: T) -> T;
- fn simd_fpowi(x: T, y: i32) -> T;
+#[rustc_intrinsic]
+unsafe fn simd_fsqrt(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fabs(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fsin(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fcos(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fexp(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fexp2(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fma(x: T, y: T, z: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_relaxed_fma(x: T, y: T, z: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_flog(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_flog10(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_flog2(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fpow(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_fpowi(x: T, y: i32) -> T;
+
+
+// rounding functions
+#[rustc_intrinsic]
+unsafe fn simd_ceil(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_floor(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_round(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_trunc(x: T) -> T;
- // rounding functions
- fn simd_ceil(x: T) -> T;
- fn simd_floor(x: T) -> T;
- fn simd_round(x: T) -> T;
- fn simd_trunc(x: T) -> T;
-}
macro_rules! assert_approx_eq_f32 {
($a:expr, $b:expr) => ({
diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs
index 663bcdf19819..0fcff8584c85 100644
--- a/tests/ui/simd/intrinsic/generic-arithmetic-2.rs
+++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.rs
@@ -14,25 +14,54 @@ pub struct u32x4(pub [u32; 4]);
#[derive(Copy, Clone)]
pub struct f32x4(pub [f32; 4]);
-extern "rust-intrinsic" {
- fn simd_add(x: T, y: T) -> T;
- fn simd_sub(x: T, y: T) -> T;
- fn simd_mul(x: T, y: T) -> T;
- fn simd_div(x: T, y: T) -> T;
- fn simd_rem(x: T, y: T) -> T;
- fn simd_shl(x: T, y: T) -> T;
- fn simd_shr(x: T, y: T) -> T;
- fn simd_and(x: T, y: T) -> T;
- fn simd_or(x: T, y: T) -> T;
- fn simd_xor(x: T, y: T) -> T;
+#[rustc_intrinsic]
+unsafe fn simd_add(x: T, y: T) -> T;
- fn simd_neg(x: T) -> T;
- fn simd_bswap(x: T) -> T;
- fn simd_bitreverse(x: T) -> T;
- fn simd_ctlz(x: T) -> T;
- fn simd_ctpop(x: T) -> T;
- fn simd_cttz(x: T) -> T;
-}
+#[rustc_intrinsic]
+unsafe fn simd_sub(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_mul(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_div(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_rem(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_shl(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_shr(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_and(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_or(x: T, y: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_xor(x: T, y: T) -> T;
+
+
+#[rustc_intrinsic]
+unsafe fn simd_neg(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_bswap(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_bitreverse(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_ctlz(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_ctpop(x: T) -> T;
+
+#[rustc_intrinsic]
+unsafe fn simd_cttz(x: T) -> T;
fn main() {
let x = i32x4([0, 0, 0, 0]);
diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr b/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr
index 6f5f86d7d374..e67de2fe9034 100644
--- a/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr
+++ b/tests/ui/simd/intrinsic/generic-arithmetic-2.stderr
@@ -1,143 +1,143 @@
error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:81:9
+ --> $DIR/generic-arithmetic-2.rs:110:9
|
LL | simd_add(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_sub` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:83:9
+ --> $DIR/generic-arithmetic-2.rs:112:9
|
LL | simd_sub(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_mul` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:85:9
+ --> $DIR/generic-arithmetic-2.rs:114:9
|
LL | simd_mul(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_div` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:87:9
+ --> $DIR/generic-arithmetic-2.rs:116:9
|
LL | simd_div(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shl` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:89:9
+ --> $DIR/generic-arithmetic-2.rs:118:9
|
LL | simd_shl(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shr` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:91:9
+ --> $DIR/generic-arithmetic-2.rs:120:9
|
LL | simd_shr(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_and` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:93:9
+ --> $DIR/generic-arithmetic-2.rs:122:9
|
LL | simd_and(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_or` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:95:9
+ --> $DIR/generic-arithmetic-2.rs:124:9
|
LL | simd_or(0, 0);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_xor` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:97:9
+ --> $DIR/generic-arithmetic-2.rs:126:9
|
LL | simd_xor(0, 0);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_neg` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:100:9
+ --> $DIR/generic-arithmetic-2.rs:129:9
|
LL | simd_neg(0);
| ^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bswap` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:102:9
+ --> $DIR/generic-arithmetic-2.rs:131:9
|
LL | simd_bswap(0);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bitreverse` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:104:9
+ --> $DIR/generic-arithmetic-2.rs:133:9
|
LL | simd_bitreverse(0);
| ^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_ctlz` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:106:9
+ --> $DIR/generic-arithmetic-2.rs:135:9
|
LL | simd_ctlz(0);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_cttz` intrinsic: expected SIMD input type, found non-SIMD `i32`
- --> $DIR/generic-arithmetic-2.rs:108:9
+ --> $DIR/generic-arithmetic-2.rs:137:9
|
LL | simd_cttz(0);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shl` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:111:9
+ --> $DIR/generic-arithmetic-2.rs:140:9
|
LL | simd_shl(z, z);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_shr` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:113:9
+ --> $DIR/generic-arithmetic-2.rs:142:9
|
LL | simd_shr(z, z);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_and` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:115:9
+ --> $DIR/generic-arithmetic-2.rs:144:9
|
LL | simd_and(z, z);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_or` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:117:9
+ --> $DIR/generic-arithmetic-2.rs:146:9
|
LL | simd_or(z, z);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_xor` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:119:9
+ --> $DIR/generic-arithmetic-2.rs:148:9
|
LL | simd_xor(z, z);
| ^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bswap` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:121:9
+ --> $DIR/generic-arithmetic-2.rs:150:9
|
LL | simd_bswap(z);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_bitreverse` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:123:9
+ --> $DIR/generic-arithmetic-2.rs:152:9
|
LL | simd_bitreverse(z);
| ^^^^^^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_ctlz` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:125:9
+ --> $DIR/generic-arithmetic-2.rs:154:9
|
LL | simd_ctlz(z);
| ^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_ctpop` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:127:9
+ --> $DIR/generic-arithmetic-2.rs:156:9
|
LL | simd_ctpop(z);
| ^^^^^^^^^^^^^
error[E0511]: invalid monomorphization of `simd_cttz` intrinsic: unsupported operation on `f32x4` with element `f32`
- --> $DIR/generic-arithmetic-2.rs:129:9
+ --> $DIR/generic-arithmetic-2.rs:158:9
|
LL | simd_cttz(z);
| ^^^^^^^^^^^^
diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
index e4eb2a9da271..4a18c0164e4b 100644
--- a/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
+++ b/tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
@@ -23,25 +23,54 @@ macro_rules! all_eq {
}};
}
-extern "rust-intrinsic" {
- fn simd_add(x: T, y: T) -> T;
- fn simd_sub