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> { ", ) 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(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 x1 = i32x4([1, 2, 3, 4]); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs index ec6ac78df1a7..85464402d6af 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs @@ -14,10 +14,12 @@ pub struct x4(pub [T; 4]); #[derive(Copy, Clone)] pub struct f32x4(pub [f32; 4]); -extern "rust-intrinsic" { - fn simd_saturating_add(x: T, y: T) -> T; - fn simd_saturating_sub(x: T, y: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_saturating_add(x: T, y: T) -> T; + +#[rustc_intrinsic] +unsafe fn simd_saturating_sub(x: T, y: T) -> T; + fn main() { let x = i32x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr index f349cb56560c..cf275db7e435 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.stderr @@ -1,11 +1,11 @@ error[E0511]: invalid monomorphization of `simd_saturating_add` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/generic-arithmetic-saturating-2.rs:33:9 + --> $DIR/generic-arithmetic-saturating-2.rs:35:9 | LL | simd_saturating_add(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_saturating_sub` intrinsic: expected element type `f32` of vector type `f32x4` to be a signed or unsigned integer type - --> $DIR/generic-arithmetic-saturating-2.rs:35:9 + --> $DIR/generic-arithmetic-saturating-2.rs:37:9 | LL | simd_saturating_sub(z, z); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs index 57bda5c2d624..5fe65257d15f 100644 --- a/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs +++ b/tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs @@ -12,10 +12,12 @@ struct u32x4(pub [u32; 4]); #[derive(Copy, Clone)] struct I32([i32; N]); -extern "rust-intrinsic" { - fn simd_saturating_add(x: T, y: T) -> T; - fn simd_saturating_sub(x: T, y: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_saturating_add(x: T, y: T) -> T; + +#[rustc_intrinsic] +unsafe fn simd_saturating_sub(x: T, y: T) -> T; + fn main() { // unsigned diff --git a/tests/ui/simd/intrinsic/generic-as.rs b/tests/ui/simd/intrinsic/generic-as.rs index e97bf12c1447..124ca56bc889 100644 --- a/tests/ui/simd/intrinsic/generic-as.rs +++ b/tests/ui/simd/intrinsic/generic-as.rs @@ -2,9 +2,9 @@ #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_as(x: T) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_as(x: T) -> U; #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs index db10020bd469..08526991fbe1 100644 --- a/tests/ui/simd/intrinsic/generic-bitmask-pass.rs +++ b/tests/ui/simd/intrinsic/generic-bitmask-pass.rs @@ -21,9 +21,8 @@ struct u8x4(pub [u8; 4]); #[derive(Copy, Clone, PartialEq, Debug)] struct Tx4(pub [T; 4]); -extern "rust-intrinsic" { - fn simd_bitmask(x: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(x: T) -> U; fn main() { let z = u32x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-bitmask.rs b/tests/ui/simd/intrinsic/generic-bitmask.rs index 29b9279c370f..49589d22bbfa 100644 --- a/tests/ui/simd/intrinsic/generic-bitmask.rs +++ b/tests/ui/simd/intrinsic/generic-bitmask.rs @@ -30,9 +30,8 @@ struct u8x32([u8; 32]); #[derive(Copy, Clone)] struct u8x64([u8; 64]); -extern "rust-intrinsic" { - fn simd_bitmask(x: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(x: T) -> U; fn main() { let m2 = u32x2([0; 2]); diff --git a/tests/ui/simd/intrinsic/generic-bitmask.stderr b/tests/ui/simd/intrinsic/generic-bitmask.stderr index 0de3f8eead86..c217bb2d8f1a 100644 --- a/tests/ui/simd/intrinsic/generic-bitmask.stderr +++ b/tests/ui/simd/intrinsic/generic-bitmask.stderr @@ -1,29 +1,29 @@ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` - --> $DIR/generic-bitmask.rs:53:22 + --> $DIR/generic-bitmask.rs:52:22 | LL | let _: u16 = simd_bitmask(m2); | ^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u16`, expected `u8` or `[u8; 1]` - --> $DIR/generic-bitmask.rs:56:22 + --> $DIR/generic-bitmask.rs:55:22 | LL | let _: u16 = simd_bitmask(m8); | ^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u32`, expected `u16` or `[u8; 2]` - --> $DIR/generic-bitmask.rs:59:22 + --> $DIR/generic-bitmask.rs:58:22 | LL | let _: u32 = simd_bitmask(m16); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u64`, expected `u32` or `[u8; 4]` - --> $DIR/generic-bitmask.rs:62:22 + --> $DIR/generic-bitmask.rs:61:22 | LL | let _: u64 = simd_bitmask(m32); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_bitmask` intrinsic: cannot return `u128`, expected `u64` or `[u8; 8]` - --> $DIR/generic-bitmask.rs:65:23 + --> $DIR/generic-bitmask.rs:64:23 | LL | let _: u128 = simd_bitmask(m64); | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-bswap-byte.rs b/tests/ui/simd/intrinsic/generic-bswap-byte.rs index f1702538165d..4521573636c0 100644 --- a/tests/ui/simd/intrinsic/generic-bswap-byte.rs +++ b/tests/ui/simd/intrinsic/generic-bswap-byte.rs @@ -10,9 +10,8 @@ struct i8x4([i8; 4]); #[derive(Copy, Clone)] struct u8x4([u8; 4]); -extern "rust-intrinsic" { - fn simd_bswap(x: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_bswap(x: T) -> T; fn main() { unsafe { diff --git a/tests/ui/simd/intrinsic/generic-cast-pass.rs b/tests/ui/simd/intrinsic/generic-cast-pass.rs index e0319a6461ad..2155d8458647 100644 --- a/tests/ui/simd/intrinsic/generic-cast-pass.rs +++ b/tests/ui/simd/intrinsic/generic-cast-pass.rs @@ -3,9 +3,9 @@ #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_cast(x: T) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_cast(x: T) -> U; use std::cmp::{max, min}; diff --git a/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs index 1c09a9fbf3bf..9f28898654f2 100644 --- a/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs +++ b/tests/ui/simd/intrinsic/generic-cast-pointer-width.rs @@ -1,9 +1,8 @@ //@ run-pass #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_cast(x: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_cast(x: T) -> U; #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/intrinsic/generic-cast.rs b/tests/ui/simd/intrinsic/generic-cast.rs index 33978a2f7395..7f398804eb4f 100644 --- a/tests/ui/simd/intrinsic/generic-cast.rs +++ b/tests/ui/simd/intrinsic/generic-cast.rs @@ -21,9 +21,8 @@ struct f32x4([f32; 4]); struct f32x8([f32; 8]); -extern "rust-intrinsic" { - fn simd_cast(x: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_cast(x: T) -> U; fn main() { let x = i32x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-cast.stderr b/tests/ui/simd/intrinsic/generic-cast.stderr index 2f9d44037afb..1b6ac03f8c96 100644 --- a/tests/ui/simd/intrinsic/generic-cast.stderr +++ b/tests/ui/simd/intrinsic/generic-cast.stderr @@ -1,23 +1,23 @@ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:32:9 + --> $DIR/generic-cast.rs:31:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:34:9 + --> $DIR/generic-cast.rs:33:9 | LL | simd_cast::(0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-cast.rs:36:9 + --> $DIR/generic-cast.rs:35:9 | LL | simd_cast::(x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_cast` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i32x8` with length 8 - --> $DIR/generic-cast.rs:38:9 + --> $DIR/generic-cast.rs:37:9 | LL | simd_cast::<_, i32x8>(x); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-comparison-pass.rs b/tests/ui/simd/intrinsic/generic-comparison-pass.rs index a4d84a4c5348..68f98372e1dc 100644 --- a/tests/ui/simd/intrinsic/generic-comparison-pass.rs +++ b/tests/ui/simd/intrinsic/generic-comparison-pass.rs @@ -14,14 +14,24 @@ struct u32x4(pub [u32; 4]); #[derive(Copy, Clone)] struct f32x4(pub [f32; 4]); -extern "rust-intrinsic" { - fn simd_eq(x: T, y: T) -> U; - fn simd_ne(x: T, y: T) -> U; - fn simd_lt(x: T, y: T) -> U; - fn simd_le(x: T, y: T) -> U; - fn simd_gt(x: T, y: T) -> U; - fn simd_ge(x: T, y: T) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_eq(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_ne(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_lt(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_le(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_gt(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_ge(x: T, y: T) -> U; macro_rules! cmp { ($method: ident($lhs: expr, $rhs: expr)) => {{ diff --git a/tests/ui/simd/intrinsic/generic-comparison.rs b/tests/ui/simd/intrinsic/generic-comparison.rs index f7f0655f3d24..e5adb49f6a3b 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.rs +++ b/tests/ui/simd/intrinsic/generic-comparison.rs @@ -11,14 +11,24 @@ struct i32x4([i32; 4]); #[allow(non_camel_case_types)] struct i16x8([i16; 8]); -extern "rust-intrinsic" { - fn simd_eq(x: T, y: T) -> U; - fn simd_ne(x: T, y: T) -> U; - fn simd_lt(x: T, y: T) -> U; - fn simd_le(x: T, y: T) -> U; - fn simd_gt(x: T, y: T) -> U; - fn simd_ge(x: T, y: T) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_eq(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_ne(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_lt(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_le(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_gt(x: T, y: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_ge(x: T, y: T) -> U; fn main() { let x = i32x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-comparison.stderr b/tests/ui/simd/intrinsic/generic-comparison.stderr index ac4d49188274..cc66d2ce40a9 100644 --- a/tests/ui/simd/intrinsic/generic-comparison.stderr +++ b/tests/ui/simd/intrinsic/generic-comparison.stderr @@ -1,107 +1,107 @@ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:27:9 + --> $DIR/generic-comparison.rs:37:9 | LL | simd_eq::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:29:9 + --> $DIR/generic-comparison.rs:39:9 | LL | simd_ne::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:31:9 + --> $DIR/generic-comparison.rs:41:9 | LL | simd_lt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:33:9 + --> $DIR/generic-comparison.rs:43:9 | LL | simd_le::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:35:9 + --> $DIR/generic-comparison.rs:45:9 | LL | simd_gt::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:37:9 + --> $DIR/generic-comparison.rs:47:9 | LL | simd_ge::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:40:9 + --> $DIR/generic-comparison.rs:50:9 | LL | simd_eq::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:42:9 + --> $DIR/generic-comparison.rs:52:9 | LL | simd_ne::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:44:9 + --> $DIR/generic-comparison.rs:54:9 | LL | simd_lt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:46:9 + --> $DIR/generic-comparison.rs:56:9 | LL | simd_le::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:48:9 + --> $DIR/generic-comparison.rs:58:9 | LL | simd_gt::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected SIMD return type, found non-SIMD `i32` - --> $DIR/generic-comparison.rs:50:9 + --> $DIR/generic-comparison.rs:60:9 | LL | simd_ge::<_, i32>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_eq` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:53:9 + --> $DIR/generic-comparison.rs:63:9 | LL | simd_eq::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ne` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:55:9 + --> $DIR/generic-comparison.rs:65:9 | LL | simd_ne::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_lt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:57:9 + --> $DIR/generic-comparison.rs:67:9 | LL | simd_lt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_le` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:59:9 + --> $DIR/generic-comparison.rs:69:9 | LL | simd_le::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_gt` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:61:9 + --> $DIR/generic-comparison.rs:71:9 | LL | simd_gt::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_ge` intrinsic: expected return type with length 4 (same as input type `i32x4`), found `i16x8` with length 8 - --> $DIR/generic-comparison.rs:63:9 + --> $DIR/generic-comparison.rs:73:9 | LL | simd_ge::<_, i16x8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-elements-pass.rs b/tests/ui/simd/intrinsic/generic-elements-pass.rs index 7b1bda4fbcd5..8cb600bc9e45 100644 --- a/tests/ui/simd/intrinsic/generic-elements-pass.rs +++ b/tests/ui/simd/intrinsic/generic-elements-pass.rs @@ -16,12 +16,15 @@ struct i32x4([i32; 4]); #[allow(non_camel_case_types)] struct i32x8([i32; 8]); -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; - fn simd_shuffle(x: T, y: T, idx: I) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_extract(x: T, idx: u32) -> E; + + +#[rustc_intrinsic] +unsafe fn simd_shuffle(x: T, y: T, idx: I) -> U; #[repr(simd)] struct SimdShuffleIdx([u32; LEN]); diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs index 5d784a25eab4..4be6645f029c 100644 --- a/tests/ui/simd/intrinsic/generic-elements.rs +++ b/tests/ui/simd/intrinsic/generic-elements.rs @@ -29,13 +29,20 @@ struct f32x4([f32; 4]); #[allow(non_camel_case_types)] struct f32x8([f32; 8]); -extern "rust-intrinsic" { - fn simd_insert(x: T, idx: u32, y: E) -> T; - fn simd_extract(x: T, idx: u32) -> E; - fn simd_shuffle(x: T, y: T, idx: I) -> U; - fn simd_shuffle_generic(x: T, y: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_insert(x: T, idx: u32, y: E) -> T; + +#[rustc_intrinsic] +unsafe fn simd_extract(x: T, idx: u32) -> E; + + +#[rustc_intrinsic] +unsafe fn simd_shuffle(x: T, y: T, idx: I) -> U; + +#[rustc_intrinsic] +unsafe fn simd_shuffle_generic(x: T, y: T) -> U; + #[repr(simd)] struct SimdShuffleIdx([u32; LEN]); diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr index fd726d753260..8104c3ba5a2e 100644 --- a/tests/ui/simd/intrinsic/generic-elements.stderr +++ b/tests/ui/simd/intrinsic/generic-elements.stderr @@ -1,125 +1,125 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:47:9 + --> $DIR/generic-elements.rs:54:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/generic-elements.rs:49:9 + --> $DIR/generic-elements.rs:56:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/generic-elements.rs:51:9 + --> $DIR/generic-elements.rs:58:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:55:9 + --> $DIR/generic-elements.rs:62:9 | LL | simd_shuffle::(0, 0, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:58:9 + --> $DIR/generic-elements.rs:65:9 | LL | simd_shuffle::(0, 0, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:61:9 + --> $DIR/generic-elements.rs:68:9 | LL | simd_shuffle::(0, 0, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:64:9 + --> $DIR/generic-elements.rs:71:9 | LL | simd_shuffle::<_, _, f32x2>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:66:9 + --> $DIR/generic-elements.rs:73:9 | LL | simd_shuffle::<_, _, f32x4>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:68:9 + --> $DIR/generic-elements.rs:75:9 | LL | simd_shuffle::<_, _, f32x8>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:71:9 + --> $DIR/generic-elements.rs:78:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:73:9 + --> $DIR/generic-elements.rs:80:9 | LL | simd_shuffle::<_, _, i32x8>(x, x, IDX4); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:75:9 + --> $DIR/generic-elements.rs:82:9 | LL | simd_shuffle::<_, _, i32x2>(x, x, IDX8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:79:9 + --> $DIR/generic-elements.rs:86:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:82:9 + --> $DIR/generic-elements.rs:89:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/generic-elements.rs:85:9 + --> $DIR/generic-elements.rs:92:9 | LL | simd_shuffle_generic::(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/generic-elements.rs:88:9 + --> $DIR/generic-elements.rs:95:9 | LL | simd_shuffle_generic::<_, f32x2, I2>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/generic-elements.rs:90:9 + --> $DIR/generic-elements.rs:97:9 | LL | simd_shuffle_generic::<_, f32x4, I4>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/generic-elements.rs:92:9 + --> $DIR/generic-elements.rs:99:9 | LL | simd_shuffle_generic::<_, f32x8, I8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:95:9 + --> $DIR/generic-elements.rs:102:9 | LL | simd_shuffle_generic::<_, i32x8, I2>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8 - --> $DIR/generic-elements.rs:97:9 + --> $DIR/generic-elements.rs:104:9 | LL | simd_shuffle_generic::<_, i32x8, I4>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/generic-elements.rs:99:9 + --> $DIR/generic-elements.rs:106:9 | LL | simd_shuffle_generic::<_, i32x2, I8>(x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-gather-pass.rs b/tests/ui/simd/intrinsic/generic-gather-pass.rs index 3315d1cdaa22..0b2cf47e9898 100644 --- a/tests/ui/simd/intrinsic/generic-gather-pass.rs +++ b/tests/ui/simd/intrinsic/generic-gather-pass.rs @@ -10,10 +10,11 @@ #[derive(Copy, Clone, PartialEq, Debug)] struct x4(pub [T; 4]); -extern "rust-intrinsic" { - fn simd_gather(x: T, y: U, z: V) -> T; - fn simd_scatter(x: T, y: U, z: V) -> (); -} +#[rustc_intrinsic] +unsafe fn simd_gather(x: T, y: U, z: V) -> T; + +#[rustc_intrinsic] +unsafe fn simd_scatter(x: T, y: U, z: V) -> (); fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; diff --git a/tests/ui/simd/intrinsic/generic-reduction-pass.rs b/tests/ui/simd/intrinsic/generic-reduction-pass.rs index 699fb396259d..8408d0f203bf 100644 --- a/tests/ui/simd/intrinsic/generic-reduction-pass.rs +++ b/tests/ui/simd/intrinsic/generic-reduction-pass.rs @@ -24,19 +24,38 @@ struct f32x4(pub [f32; 4]); #[derive(Copy, Clone)] struct b8x4(pub [i8; 4]); -extern "rust-intrinsic" { - fn simd_reduce_add_unordered(x: T) -> U; - fn simd_reduce_mul_unordered(x: T) -> U; - fn simd_reduce_add_ordered(x: T, acc: U) -> U; - fn simd_reduce_mul_ordered(x: T, acc: U) -> U; - fn simd_reduce_min(x: T) -> U; - fn simd_reduce_max(x: T) -> U; - fn simd_reduce_and(x: T) -> U; - fn simd_reduce_or(x: T) -> U; - fn simd_reduce_xor(x: T) -> U; - fn simd_reduce_all(x: T) -> bool; - fn simd_reduce_any(x: T) -> bool; -} +#[rustc_intrinsic] +unsafe fn simd_reduce_add_unordered(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_mul_unordered(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_add_ordered(x: T, acc: U) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_mul_ordered(x: T, acc: U) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_min(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_max(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_and(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_or(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_xor(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_all(x: T) -> bool; + +#[rustc_intrinsic] +unsafe fn simd_reduce_any(x: T) -> bool; fn main() { unsafe { diff --git a/tests/ui/simd/intrinsic/generic-reduction.rs b/tests/ui/simd/intrinsic/generic-reduction.rs index 1986deafb6ab..ead13250643c 100644 --- a/tests/ui/simd/intrinsic/generic-reduction.rs +++ b/tests/ui/simd/intrinsic/generic-reduction.rs @@ -15,16 +15,26 @@ pub struct f32x4(pub [f32; 4]); #[derive(Copy, Clone)] pub struct u32x4(pub [u32; 4]); +#[rustc_intrinsic] +unsafe fn simd_reduce_add_ordered(x: T, y: U) -> U; -extern "rust-intrinsic" { - fn simd_reduce_add_ordered(x: T, y: U) -> U; - fn simd_reduce_mul_ordered(x: T, y: U) -> U; - fn simd_reduce_and(x: T) -> U; - fn simd_reduce_or(x: T) -> U; - fn simd_reduce_xor(x: T) -> U; - fn simd_reduce_all(x: T) -> bool; - fn simd_reduce_any(x: T) -> bool; -} +#[rustc_intrinsic] +unsafe fn simd_reduce_mul_ordered(x: T, y: U) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_and(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_or(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_xor(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_reduce_all(x: T) -> bool; + +#[rustc_intrinsic] +unsafe fn simd_reduce_any(x: T) -> bool; fn main() { let x = u32x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-reduction.stderr b/tests/ui/simd/intrinsic/generic-reduction.stderr index 1028faf69a7b..302b9ae1d778 100644 --- a/tests/ui/simd/intrinsic/generic-reduction.stderr +++ b/tests/ui/simd/intrinsic/generic-reduction.stderr @@ -1,59 +1,59 @@ error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` - --> $DIR/generic-reduction.rs:34:9 + --> $DIR/generic-reduction.rs:44:9 | LL | simd_reduce_add_ordered(z, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` - --> $DIR/generic-reduction.rs:36:9 + --> $DIR/generic-reduction.rs:46:9 | LL | simd_reduce_mul_ordered(z, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/generic-reduction.rs:39:22 + --> $DIR/generic-reduction.rs:49:22 | LL | let _: f32 = simd_reduce_and(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/generic-reduction.rs:41:22 + --> $DIR/generic-reduction.rs:51:22 | LL | let _: f32 = simd_reduce_or(x); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/generic-reduction.rs:43:22 + --> $DIR/generic-reduction.rs:53:22 | LL | let _: f32 = simd_reduce_xor(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` - --> $DIR/generic-reduction.rs:46:22 + --> $DIR/generic-reduction.rs:56:22 | LL | let _: f32 = simd_reduce_and(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` - --> $DIR/generic-reduction.rs:48:22 + --> $DIR/generic-reduction.rs:58:22 | LL | let _: f32 = simd_reduce_or(z); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` - --> $DIR/generic-reduction.rs:50:22 + --> $DIR/generic-reduction.rs:60:22 | LL | let _: f32 = simd_reduce_xor(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` - --> $DIR/generic-reduction.rs:53:23 + --> $DIR/generic-reduction.rs:63:23 | LL | let _: bool = simd_reduce_all(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` - --> $DIR/generic-reduction.rs:55:23 + --> $DIR/generic-reduction.rs:65:23 | LL | let _: bool = simd_reduce_any(z); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-select-pass.rs b/tests/ui/simd/intrinsic/generic-select-pass.rs index 5690bad50484..6b1b6cb79dbc 100644 --- a/tests/ui/simd/intrinsic/generic-select-pass.rs +++ b/tests/ui/simd/intrinsic/generic-select-pass.rs @@ -29,10 +29,12 @@ struct f32x4(pub [f32; 4]); #[derive(Copy, Clone, PartialEq, Debug)] struct b8x4(pub [i8; 4]); -extern "rust-intrinsic" { - fn simd_select(x: T, a: U, b: U) -> U; - fn simd_select_bitmask(x: T, a: U, b: U) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_select(x: T, a: U, b: U) -> U; + +#[rustc_intrinsic] +unsafe fn simd_select_bitmask(x: T, a: U, b: U) -> U; + fn main() { let m0 = b8x4([!0, !0, !0, !0]); diff --git a/tests/ui/simd/intrinsic/generic-select.rs b/tests/ui/simd/intrinsic/generic-select.rs index 52e02649590a..340fe3f35929 100644 --- a/tests/ui/simd/intrinsic/generic-select.rs +++ b/tests/ui/simd/intrinsic/generic-select.rs @@ -22,10 +22,13 @@ struct b8x4(pub [i8; 4]); #[derive(Copy, Clone, PartialEq)] struct b8x8(pub [i8; 8]); -extern "rust-intrinsic" { - fn simd_select(x: T, a: U, b: U) -> U; - fn simd_select_bitmask(x: T, a: U, b: U) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_select(x: T, a: U, b: U) -> U; + +#[rustc_intrinsic] +unsafe fn simd_select_bitmask(x: T, a: U, b: U) -> U; + fn main() { let m4 = b8x4([0, 0, 0, 0]); diff --git a/tests/ui/simd/intrinsic/generic-select.stderr b/tests/ui/simd/intrinsic/generic-select.stderr index d576f1bc7747..a97fc91f951d 100644 --- a/tests/ui/simd/intrinsic/generic-select.stderr +++ b/tests/ui/simd/intrinsic/generic-select.stderr @@ -1,47 +1,47 @@ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mismatched lengths: mask length `8` != other vector length `4` - --> $DIR/generic-select.rs:39:9 + --> $DIR/generic-select.rs:42:9 | LL | simd_select(m8, x, x); | ^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `u32`, expected `i_` - --> $DIR/generic-select.rs:42:9 + --> $DIR/generic-select.rs:45:9 | LL | simd_select(x, x, x); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: mask element type is `f32`, expected `i_` - --> $DIR/generic-select.rs:45:9 + --> $DIR/generic-select.rs:48:9 | LL | simd_select(z, z, z); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select` intrinsic: expected SIMD argument type, found non-SIMD `u32` - --> $DIR/generic-select.rs:48:9 + --> $DIR/generic-select.rs:51:9 | LL | simd_select(m4, 0u32, 1u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `u16`, expected `u8` or `[u8; 1]` - --> $DIR/generic-select.rs:51:9 + --> $DIR/generic-select.rs:54:9 | LL | simd_select_bitmask(0u16, x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: expected SIMD argument type, found non-SIMD `u32` - --> $DIR/generic-select.rs:54:9 + --> $DIR/generic-select.rs:57:9 | LL | simd_select_bitmask(0u8, 1u32, 2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `f32`, expected `u8` or `[u8; 1]` - --> $DIR/generic-select.rs:57:9 + --> $DIR/generic-select.rs:60:9 | LL | simd_select_bitmask(0.0f32, x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_select_bitmask` intrinsic: invalid bitmask `&str`, expected `u8` or `[u8; 1]` - --> $DIR/generic-select.rs:60:9 + --> $DIR/generic-select.rs:63:9 | LL | simd_select_bitmask("x", x, x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/simd/intrinsic/generic-shuffle.rs b/tests/ui/simd/intrinsic/generic-shuffle.rs index 2752718d99d6..1223b8ebe190 100644 --- a/tests/ui/simd/intrinsic/generic-shuffle.rs +++ b/tests/ui/simd/intrinsic/generic-shuffle.rs @@ -9,9 +9,9 @@ #[derive(Copy, Clone)] pub struct Simd([T; N]); -extern "rust-intrinsic" { - fn simd_shuffle(a: T, b: T, i: I) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_shuffle(a: T, b: T, i: I) -> U; + fn main() { const I: Simd = Simd([0; 2]); diff --git a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs index d9239ef5801a..b324ac40749f 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557-ice.rs @@ -5,9 +5,8 @@ //@ compile-flags: -Zmir-opt-level=4 #![feature(intrinsics, repr_simd)] -extern "rust-intrinsic" { - fn simd_shuffle(x: T, y: T, idx: I) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_shuffle(x: T, y: T, idx: I) -> U; #[repr(simd)] #[derive(Debug, PartialEq)] diff --git a/tests/ui/simd/intrinsic/inlining-issue67557.rs b/tests/ui/simd/intrinsic/inlining-issue67557.rs index 23dd5075f96b..319bb15c0157 100644 --- a/tests/ui/simd/intrinsic/inlining-issue67557.rs +++ b/tests/ui/simd/intrinsic/inlining-issue67557.rs @@ -5,9 +5,8 @@ //@ compile-flags: -Zmir-opt-level=4 #![feature(intrinsics, repr_simd)] -extern "rust-intrinsic" { - fn simd_shuffle(x: T, y: T, idx: I) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_shuffle(x: T, y: T, idx: I) -> U; #[repr(simd)] #[derive(Debug, PartialEq)] diff --git a/tests/ui/simd/intrinsic/issue-85855.rs b/tests/ui/simd/intrinsic/issue-85855.rs index dc04699f7f89..daeea793d1bc 100644 --- a/tests/ui/simd/intrinsic/issue-85855.rs +++ b/tests/ui/simd/intrinsic/issue-85855.rs @@ -5,15 +5,18 @@ #![feature(intrinsics)] #![crate_type="lib"] -extern "rust-intrinsic" { - fn simd_saturating_add<'a, T: 'a>(x: T, y: T); - //~^ ERROR: intrinsic has wrong number of lifetime parameters - fn simd_add<'a, T>(x: T, y: T) -> T; +#[rustc_intrinsic] +unsafe fn simd_saturating_add<'a, T: 'a>(x: T, y: T); +//~^ ERROR: intrinsic has wrong number of lifetime parameters - fn simd_sub(x: T, y: U); - //~^ ERROR: intrinsic has wrong number of type parameters +#[rustc_intrinsic] +unsafe fn simd_add<'a, T>(x: T, y: T) -> T; - fn simd_mul(x: T, y: T); - //~^ ERROR: intrinsic has wrong number of const parameters -} +#[rustc_intrinsic] +unsafe fn simd_sub(x: T, y: U); +//~^ ERROR: intrinsic has wrong number of type parameters + +#[rustc_intrinsic] +unsafe fn simd_mul(x: T, y: T); +//~^ ERROR: intrinsic has wrong number of const parameters diff --git a/tests/ui/simd/intrinsic/issue-85855.stderr b/tests/ui/simd/intrinsic/issue-85855.stderr index fb2f1fbc5b1c..b91a606ba68a 100644 --- a/tests/ui/simd/intrinsic/issue-85855.stderr +++ b/tests/ui/simd/intrinsic/issue-85855.stderr @@ -1,20 +1,20 @@ error[E0094]: intrinsic has wrong number of lifetime parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:9:27 + --> $DIR/issue-85855.rs:10:30 | -LL | fn simd_saturating_add<'a, T: 'a>(x: T, y: T); - | ^^^^^^^^^^^ expected 0 lifetime parameters +LL | unsafe fn simd_saturating_add<'a, T: 'a>(x: T, y: T); + | ^^^^^^^^^^^ expected 0 lifetime parameters error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1 - --> $DIR/issue-85855.rs:14:16 + --> $DIR/issue-85855.rs:17:19 | -LL | fn simd_sub(x: T, y: U); - | ^^^^^^ expected 1 type parameter +LL | unsafe fn simd_sub(x: T, y: U); + | ^^^^^^ expected 1 type parameter error[E0094]: intrinsic has wrong number of const parameters: found 1, expected 0 - --> $DIR/issue-85855.rs:17:16 + --> $DIR/issue-85855.rs:21:19 | -LL | fn simd_mul(x: T, y: T); - | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters +LL | unsafe fn simd_mul(x: T, y: T); + | ^^^^^^^^^^^^^^^^^^^ expected 0 const parameters error: aborting due to 3 previous errors diff --git a/tests/ui/simd/intrinsic/ptr-cast.rs b/tests/ui/simd/intrinsic/ptr-cast.rs index 0490734b48ac..559b8ba1b5c2 100644 --- a/tests/ui/simd/intrinsic/ptr-cast.rs +++ b/tests/ui/simd/intrinsic/ptr-cast.rs @@ -2,11 +2,15 @@ #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_cast_ptr(x: T) -> U; - fn simd_expose_provenance(x: T) -> U; - fn simd_with_exposed_provenance(x: T) -> U; -} + +#[rustc_intrinsic] +unsafe fn simd_cast_ptr(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_expose_provenance(x: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_with_exposed_provenance(x: T) -> U; #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/issue-105439.rs b/tests/ui/simd/issue-105439.rs index 3cb43fc8b1af..108bb282df2a 100644 --- a/tests/ui/simd/issue-105439.rs +++ b/tests/ui/simd/issue-105439.rs @@ -9,9 +9,8 @@ #[repr(simd)] struct i32x4([i32; 4]); -extern "rust-intrinsic" { - pub(crate) fn simd_add(x: T, y: T) -> T; -} +#[rustc_intrinsic] +pub(crate) unsafe fn simd_add(x: T, y: T) -> T; #[inline(always)] fn to_array(a: i32x4) -> [i32; 4] { diff --git a/tests/ui/simd/issue-39720.rs b/tests/ui/simd/issue-39720.rs index 2b51c0224c63..8d7666faaf93 100644 --- a/tests/ui/simd/issue-39720.rs +++ b/tests/ui/simd/issue-39720.rs @@ -11,9 +11,8 @@ pub struct Char3(pub [i8; 3]); #[derive(Copy, Clone, Debug)] pub struct Short3(pub [i16; 3]); -extern "rust-intrinsic" { - fn simd_cast(x: T) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_cast(x: T) -> U; fn main() { let cast: Short3 = unsafe { simd_cast(Char3([10, -3, -9])) }; diff --git a/tests/ui/simd/issue-85915-simd-ptrs.rs b/tests/ui/simd/issue-85915-simd-ptrs.rs index edf60e0205c2..2e7baf48ee32 100644 --- a/tests/ui/simd/issue-85915-simd-ptrs.rs +++ b/tests/ui/simd/issue-85915-simd-ptrs.rs @@ -22,10 +22,12 @@ struct f32x4([f32; 4]); #[derive(Copy, Clone, PartialEq, Debug)] struct i32x4([i32; 4]); -extern "rust-intrinsic" { - fn simd_gather(x: T, y: U, z: V) -> T; - fn simd_scatter(x: T, y: U, z: V) -> (); -} + +#[rustc_intrinsic] +unsafe fn simd_gather(x: T, y: U, z: V) -> T; + +#[rustc_intrinsic] +unsafe fn simd_scatter(x: T, y: U, z: V) -> (); fn main() { let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.]; diff --git a/tests/ui/simd/issue-89193.rs b/tests/ui/simd/issue-89193.rs index 9530124a7cc8..4b4fb9d91696 100644 --- a/tests/ui/simd/issue-89193.rs +++ b/tests/ui/simd/issue-89193.rs @@ -10,9 +10,8 @@ #[derive(Copy, Clone, PartialEq, Debug)] struct x4(pub [T; 4]); -extern "rust-intrinsic" { - fn simd_gather(x: T, y: U, z: V) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_gather(x: T, y: U, z: V) -> T; fn main() { let x: [usize; 4] = [10, 11, 12, 13]; diff --git a/tests/ui/simd/masked-load-store-build-fail.rs b/tests/ui/simd/masked-load-store-build-fail.rs index fbd657763c98..b8742184eb02 100644 --- a/tests/ui/simd/masked-load-store-build-fail.rs +++ b/tests/ui/simd/masked-load-store-build-fail.rs @@ -1,10 +1,12 @@ //@ build-fail #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_masked_load(mask: M, pointer: P, values: T) -> T; - fn simd_masked_store(mask: M, pointer: P, values: T) -> (); -} + +#[rustc_intrinsic] +unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; + +#[rustc_intrinsic] +unsafe fn simd_masked_store(mask: M, pointer: P, values: T) -> (); #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/masked-load-store-build-fail.stderr b/tests/ui/simd/masked-load-store-build-fail.stderr index 59af83fe0e89..8a8d8eb99e27 100644 --- a/tests/ui/simd/masked-load-store-build-fail.stderr +++ b/tests/ui/simd/masked-load-store-build-fail.stderr @@ -1,5 +1,5 @@ error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected third argument with length 8 (same as input type `Simd`), found `Simd` with length 4 - --> $DIR/masked-load-store-build-fail.rs:18:9 + --> $DIR/masked-load-store-build-fail.rs:20:9 | LL | / simd_masked_load( LL | | Simd::([-1, 0, -1, -1, 0, 0, 0, 0]), @@ -9,7 +9,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd`, found `u8` != `*_ u8` - --> $DIR/masked-load-store-build-fail.rs:25:9 + --> $DIR/masked-load-store-build-fail.rs:27:9 | LL | / simd_masked_load( LL | | Simd::([-1, 0, -1, -1]), @@ -19,7 +19,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd`, found `u32` != `*_ u32` - --> $DIR/masked-load-store-build-fail.rs:32:9 + --> $DIR/masked-load-store-build-fail.rs:34:9 | LL | / simd_masked_load( LL | | Simd::([-1, 0, -1, -1]), @@ -29,7 +29,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of third argument `Simd` to be a signed integer type - --> $DIR/masked-load-store-build-fail.rs:39:9 + --> $DIR/masked-load-store-build-fail.rs:41:9 | LL | / simd_masked_load( LL | | Simd::([1, 0, 1, 1]), @@ -39,7 +39,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd`, found `u32` != `*mut u32` - --> $DIR/masked-load-store-build-fail.rs:46:9 + --> $DIR/masked-load-store-build-fail.rs:48:9 | LL | / simd_masked_store( LL | | Simd([-1i8; 4]), @@ -49,7 +49,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd`, found `u8` != `*mut u8` - --> $DIR/masked-load-store-build-fail.rs:53:9 + --> $DIR/masked-load-store-build-fail.rs:55:9 | LL | / simd_masked_store( LL | | Simd([-1i8; 4]), @@ -59,7 +59,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected third argument with length 4 (same as input type `Simd`), found `Simd` with length 2 - --> $DIR/masked-load-store-build-fail.rs:60:9 + --> $DIR/masked-load-store-build-fail.rs:62:9 | LL | / simd_masked_store( LL | | Simd([-1i8; 4]), @@ -69,7 +69,7 @@ LL | | ); | |_________^ error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of third argument `Simd` to be a signed integer type - --> $DIR/masked-load-store-build-fail.rs:67:9 + --> $DIR/masked-load-store-build-fail.rs:69:9 | LL | / simd_masked_store( LL | | Simd([1u32; 4]), diff --git a/tests/ui/simd/masked-load-store-check-fail.rs b/tests/ui/simd/masked-load-store-check-fail.rs index 39c82c41385c..0f36bf6443f9 100644 --- a/tests/ui/simd/masked-load-store-check-fail.rs +++ b/tests/ui/simd/masked-load-store-check-fail.rs @@ -1,10 +1,11 @@ //@ check-fail #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_masked_load(mask: M, pointer: P, values: T) -> T; - fn simd_masked_store(mask: M, pointer: P, values: T) -> (); -} +#[rustc_intrinsic] +unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; + +#[rustc_intrinsic] +unsafe fn simd_masked_store(mask: M, pointer: P, values: T) -> (); #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/masked-load-store-check-fail.stderr b/tests/ui/simd/masked-load-store-check-fail.stderr index 5d205d607c9f..fa65798fc94d 100644 --- a/tests/ui/simd/masked-load-store-check-fail.stderr +++ b/tests/ui/simd/masked-load-store-check-fail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/masked-load-store-check-fail.rs:21:13 + --> $DIR/masked-load-store-check-fail.rs:22:13 | LL | let _x: Simd = simd_masked_load( | ---------------- arguments to this function are incorrect @@ -10,7 +10,7 @@ LL | Simd::([9; 4]) = note: expected struct `Simd<_, 2>` found struct `Simd<_, 4>` help: the return type of this call is `Simd` due to the type of the argument passed - --> $DIR/masked-load-store-check-fail.rs:18:31 + --> $DIR/masked-load-store-check-fail.rs:19:31 | LL | let _x: Simd = simd_masked_load( | _______________________________^ @@ -21,13 +21,13 @@ LL | | Simd::([9; 4]) LL | | ); | |_________^ note: function defined here - --> $DIR/masked-load-store-check-fail.rs:5:8 + --> $DIR/masked-load-store-check-fail.rs:5:11 | -LL | fn simd_masked_load(mask: M, pointer: P, values: T) -> T; - | ^^^^^^^^^^^^^^^^ +LL | unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; + | ^^^^^^^^^^^^^^^^ --------- error[E0308]: mismatched types - --> $DIR/masked-load-store-check-fail.rs:28:13 + --> $DIR/masked-load-store-check-fail.rs:29:13 | LL | let _x: Simd = simd_masked_load( | ---------------- arguments to this function are incorrect @@ -38,7 +38,7 @@ LL | default = note: expected struct `Simd` found struct `Simd` help: the return type of this call is `Simd` due to the type of the argument passed - --> $DIR/masked-load-store-check-fail.rs:25:32 + --> $DIR/masked-load-store-check-fail.rs:26:32 | LL | let _x: Simd = simd_masked_load( | ________________________________^ @@ -49,10 +49,10 @@ LL | | default LL | | ); | |_________^ note: function defined here - --> $DIR/masked-load-store-check-fail.rs:5:8 + --> $DIR/masked-load-store-check-fail.rs:5:11 | -LL | fn simd_masked_load(mask: M, pointer: P, values: T) -> T; - | ^^^^^^^^^^^^^^^^ +LL | unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; + | ^^^^^^^^^^^^^^^^ --------- error: aborting due to 2 previous errors diff --git a/tests/ui/simd/masked-load-store.rs b/tests/ui/simd/masked-load-store.rs index 902143f92615..4b4195f51f18 100644 --- a/tests/ui/simd/masked-load-store.rs +++ b/tests/ui/simd/masked-load-store.rs @@ -1,10 +1,11 @@ //@ run-pass #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_masked_load(mask: M, pointer: P, values: T) -> T; - fn simd_masked_store(mask: M, pointer: P, values: T) -> (); -} +#[rustc_intrinsic] +unsafe fn simd_masked_load(mask: M, pointer: P, values: T) -> T; + +#[rustc_intrinsic] +unsafe fn simd_masked_store(mask: M, pointer: P, values: T) -> (); #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr index 2d1fa1f8da22..b0a8da59fac1 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr +++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr @@ -1,5 +1,5 @@ error: overly complex generic constant - --> $DIR/monomorphize-shuffle-index.rs:29:45 + --> $DIR/monomorphize-shuffle-index.rs:32:45 | LL | return simd_shuffle_generic::<_, _, { &Self::I.0 }>(a, b); | ^^----------^^ diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs index 140cf6fbe96a..01926408a2ce 100644 --- a/tests/ui/simd/monomorphize-shuffle-index.rs +++ b/tests/ui/simd/monomorphize-shuffle-index.rs @@ -4,12 +4,15 @@ #![feature(repr_simd, intrinsics, adt_const_params, unsized_const_params, generic_const_exprs)] #![allow(incomplete_features)] -extern "rust-intrinsic" { - #[cfg(old)] - fn simd_shuffle(a: T, b: T, i: I) -> U; - #[cfg(any(generic, generic_with_fn))] - fn simd_shuffle_generic(a: T, b: T) -> U; -} + +#[rustc_intrinsic] +#[cfg(old)] +unsafe fn simd_shuffle(a: T, b: T, i: I) -> U; + +#[rustc_intrinsic] +#[cfg(any(generic, generic_with_fn))] +unsafe fn simd_shuffle_generic(a: T, b: T) -> U; + #[derive(Copy, Clone)] #[repr(simd)] diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs index 1ba15bda98dd..a666892226ea 100644 --- a/tests/ui/simd/repr_packed.rs +++ b/tests/ui/simd/repr_packed.rs @@ -22,9 +22,8 @@ fn check_ty() { check_size_align::(); } -extern "rust-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_add(a: T, b: T) -> T; fn main() { check_ty::(); diff --git a/tests/ui/simd/shuffle.rs b/tests/ui/simd/shuffle.rs index 96c0ed2118f9..2cae5a1e7de2 100644 --- a/tests/ui/simd/shuffle.rs +++ b/tests/ui/simd/shuffle.rs @@ -8,9 +8,8 @@ use std::marker::ConstParamTy; -extern "rust-intrinsic" { - fn simd_shuffle(a: T, b: T, i: I) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_shuffle(a: T, b: T, i: I) -> U; #[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)] #[repr(simd)] diff --git a/tests/ui/simd/simd-bitmask-notpow2.rs b/tests/ui/simd/simd-bitmask-notpow2.rs index 3499bf33ed57..d7572ef4a2a4 100644 --- a/tests/ui/simd/simd-bitmask-notpow2.rs +++ b/tests/ui/simd/simd-bitmask-notpow2.rs @@ -4,10 +4,12 @@ //@ ignore-endian-big #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_bitmask(v: T) -> U; - fn simd_select_bitmask(m: T, a: U, b: U) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(v: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_select_bitmask(m: T, a: U, b: U) -> U; + fn main() { // Non-power-of-2 multi-byte mask. diff --git a/tests/ui/simd/simd-bitmask.rs b/tests/ui/simd/simd-bitmask.rs index 82f73fca9512..4275ab0f40c9 100644 --- a/tests/ui/simd/simd-bitmask.rs +++ b/tests/ui/simd/simd-bitmask.rs @@ -1,10 +1,12 @@ //@run-pass #![feature(repr_simd, intrinsics)] -extern "rust-intrinsic" { - fn simd_bitmask(v: T) -> U; - fn simd_select_bitmask(m: T, a: U, b: U) -> U; -} +#[rustc_intrinsic] +unsafe fn simd_bitmask(v: T) -> U; + +#[rustc_intrinsic] +unsafe fn simd_select_bitmask(m: T, a: U, b: U) -> U; + #[derive(Copy, Clone)] #[repr(simd)] From cc7e3a6228e3016c069b7f62ed40004ede6fafb8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:54:18 +0000 Subject: [PATCH 31/68] Remove stabilized feature gate --- library/std/tests/floats/lib.rs | 2 +- library/std/tests/sync/lib.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/library/std/tests/floats/lib.rs b/library/std/tests/floats/lib.rs index 79813871ed94..ad82f1a44e71 100644 --- a/library/std/tests/floats/lib.rs +++ b/library/std/tests/floats/lib.rs @@ -1,4 +1,4 @@ -#![feature(f16, f128, float_gamma, float_next_up_down, float_minimum_maximum)] +#![feature(f16, f128, float_gamma, float_minimum_maximum)] use std::fmt; use std::ops::{Add, Div, Mul, Rem, Sub}; diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs index 6bf320d52f21..51190f0894fb 100644 --- a/library/std/tests/sync/lib.rs +++ b/library/std/tests/sync/lib.rs @@ -2,7 +2,6 @@ #![feature(mapped_lock_guards)] #![feature(mpmc_channel)] #![feature(once_cell_try)] -#![feature(once_wait)] #![feature(lock_value_accessors)] #![feature(reentrant_lock)] #![feature(rwlock_downgrade)] From 7de67a16c57872a0529384bac04bbbe01eebc221 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 12:51:58 +1100 Subject: [PATCH 32/68] Flatten the option check in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2..f8f00c02ad2c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -159,38 +159,35 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { (Option>, Option>, Option), ErrorGuaranteed, > { - match expr { - None => Ok((None, None, None)), - Some(expr) => { - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); - } - }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + let Some(expr) = expr else { return Ok((None, None, None)) }; + + let (kind, ascr, inline_const) = match self.lower_lit(expr) { + PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { + (subpattern.kind, None, def_id.as_local()) } - } + PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { + (subpattern.kind, None, None) + } + PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { + (kind, Some(ascription), None) + } + kind => (kind, None, None), + }; + let value = match kind { + PatKind::Constant { value } => value, + PatKind::ExpandedConstant { subpattern, .. } + if let PatKind::Constant { value } = subpattern.kind => + { + value + } + _ => { + let msg = format!( + "found bad range pattern endpoint `{expr:?}` outside of error recovery" + ); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + } + }; + Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we From 85f4cdc62692f27e897ba0da2cd5fae30a19f740 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:18:04 +1100 Subject: [PATCH 33/68] Return range endpoint ascriptions/consts via a `&mut Vec` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f8f00c02ad2c..3aa2b343b557 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -155,11 +155,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range_endpoint( &mut self, expr: Option<&'tcx hir::PatExpr<'tcx>>, - ) -> Result< - (Option>, Option>, Option), - ErrorGuaranteed, - > { - let Some(expr) = expr else { return Ok((None, None, None)) }; + // Out-parameters collecting extra data to be reapplied by the caller + ascriptions: &mut Vec>, + inline_consts: &mut Vec, + ) -> Result>, ErrorGuaranteed> { + let Some(expr) = expr else { return Ok(None) }; let (kind, ascr, inline_const) = match self.lower_lit(expr) { PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { @@ -187,7 +187,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); } }; - Ok((Some(PatRangeBoundary::Finite(value)), ascr, inline_const)) + + ascriptions.extend(ascr); + inline_consts.extend(inline_const); + Ok(Some(PatRangeBoundary::Finite(value))) } /// Overflowing literals are linted against in a late pass. This is mostly fine, except when we @@ -250,11 +253,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.tcx.dcx().span_bug(span, msg); } - let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?; - let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?; + // Collect extra data while lowering the endpoints, to be reapplied later. + let mut ascriptions = vec![]; + let mut inline_consts = vec![]; - let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); - let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); + let mut lower_endpoint = + |expr| self.lower_pattern_range_endpoint(expr, &mut ascriptions, &mut inline_consts); + + let lo = lower_endpoint(lo_expr)?.unwrap_or(PatRangeBoundary::NegInfinity); + let hi = lower_endpoint(hi_expr)?.unwrap_or(PatRangeBoundary::PosInfinity); let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); @@ -295,13 +302,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // If we are handling a range with associated constants (e.g. // `Foo::<'a>::A..=Foo::B`), we need to put the ascriptions for the associated // constants somewhere. Have them on the range pattern. - for ascription in [lo_ascr, hi_ascr].into_iter().flatten() { + for ascription in ascriptions { kind = PatKind::AscribeUserType { ascription, subpattern: Box::new(Pat { span, ty, kind }), }; } - for def in [lo_inline, hi_inline].into_iter().flatten() { + for def in inline_consts { kind = PatKind::ExpandedConstant { def_id: def.to_def_id(), is_inline: true, From 2fb1261c2156087d003359db25b13b282934669c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Feb 2025 14:29:13 +1100 Subject: [PATCH 34/68] Simplify the pattern unpeeling in `lower_pattern_range_endpoint` --- .../rustc_mir_build/src/thir/pattern/mod.rs | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 3aa2b343b557..0aa61152330a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -161,35 +161,34 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ) -> Result>, ErrorGuaranteed> { let Some(expr) = expr else { return Ok(None) }; - let (kind, ascr, inline_const) = match self.lower_lit(expr) { - PatKind::ExpandedConstant { subpattern, def_id, is_inline: true } => { - (subpattern.kind, None, def_id.as_local()) - } - PatKind::ExpandedConstant { subpattern, is_inline: false, .. } => { - (subpattern.kind, None, None) - } - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription), None) - } - kind => (kind, None, None), - }; - let value = match kind { - PatKind::Constant { value } => value, - PatKind::ExpandedConstant { subpattern, .. } - if let PatKind::Constant { value } = subpattern.kind => - { - value - } - _ => { - let msg = format!( - "found bad range pattern endpoint `{expr:?}` outside of error recovery" - ); - return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); + // Lower the endpoint into a temporary `PatKind` that will then be + // deconstructed to obtain the constant value and other data. + let mut kind: PatKind<'tcx> = self.lower_lit(expr); + + // Unpeel any ascription or inline-const wrapper nodes. + loop { + match kind { + PatKind::AscribeUserType { ascription, subpattern } => { + ascriptions.push(ascription); + kind = subpattern.kind; + } + PatKind::ExpandedConstant { is_inline, def_id, subpattern } => { + if is_inline { + inline_consts.extend(def_id.as_local()); + } + kind = subpattern.kind; + } + _ => break, } + } + + // The unpeeled kind should now be a constant, giving us the endpoint value. + let PatKind::Constant { value } = kind else { + let msg = + format!("found bad range pattern endpoint `{expr:?}` outside of error recovery"); + return Err(self.tcx.dcx().span_delayed_bug(expr.span, msg)); }; - ascriptions.extend(ascr); - inline_consts.extend(inline_const); Ok(Some(PatRangeBoundary::Finite(value))) } From f46e6be1908c7ed729655c8f601548f732ef49f4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 2 Feb 2025 19:23:44 -0800 Subject: [PATCH 35/68] Handle the case where the `or disjoint` folds immediately to a constant --- compiler/rustc_codegen_llvm/src/builder.rs | 8 +++++++- tests/codegen/intrinsics/disjoint_bitor.rs | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 6e1eec4f0fc9..264d43c6d46e 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -424,7 +424,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { 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); + + // If a and b are both values, then `or` is a value, rather than + // an instruction, so we need to check before setting the flag. + // (See also `LLVMBuildNUWNeg` which also needs a check.) + if llvm::LLVMIsAInstruction(or).is_some() { + llvm::LLVMSetIsDisjoint(or, True); + } or } } diff --git a/tests/codegen/intrinsics/disjoint_bitor.rs b/tests/codegen/intrinsics/disjoint_bitor.rs index be9954507b3f..fc45439ee0b9 100644 --- a/tests/codegen/intrinsics/disjoint_bitor.rs +++ b/tests/codegen/intrinsics/disjoint_bitor.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -C no-prepopulate-passes +//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 #![crate_type = "lib"] #![feature(core_intrinsics)] @@ -18,3 +18,13 @@ pub unsafe fn disjoint_bitor_unsigned(x: u64, y: u64) -> u64 { // CHECK: or disjoint i64 %x, %y disjoint_bitor(x, y) } + +// CHECK-LABEL: @disjoint_bitor_literal +#[no_mangle] +pub unsafe fn disjoint_bitor_literal() -> u8 { + // This is a separate check because even without any passes, + // LLVM will fold so it's not an instruction, which can assert in LLVM. + + // CHECK: store i8 3 + disjoint_bitor(1, 2) +} From f0308938ba39bc3377f22f7479654ba32e9c233f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Jan 2025 10:24:16 +0000 Subject: [PATCH 36/68] Use a different hir type for patterns in pattern types than we use in match patterns --- compiler/rustc_ast_lowering/src/index.rs | 8 +- compiler/rustc_ast_lowering/src/lib.rs | 4 +- compiler/rustc_ast_lowering/src/pat.rs | 80 ++++++++++++++++++- compiler/rustc_driver_impl/src/pretty.rs | 4 + compiler/rustc_hir/src/hir.rs | 21 ++++- compiler/rustc_hir/src/intravisit.rs | 18 ++++- compiler/rustc_hir_analysis/messages.ftl | 3 - .../src/collect/resolve_bound_vars.rs | 4 +- .../rustc_hir_analysis/src/collect/type_of.rs | 21 +++-- compiler/rustc_hir_analysis/src/errors.rs | 7 -- .../src/errors/pattern_types.rs | 7 -- .../src/hir_ty_lowering/mod.rs | 65 ++------------- compiler/rustc_hir_pretty/src/lib.rs | 51 +++++++++--- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 2 + compiler/rustc_passes/src/hir_id_validator.rs | 4 +- .../clippy/clippy_utils/src/hir_utils.rs | 20 ++++- .../bad_const_generics_args_on_const_param.rs | 1 + ..._const_generics_args_on_const_param.stderr | 10 ++- tests/ui/type/pattern_types/bad_pat.rs | 2 +- tests/ui/type/pattern_types/bad_pat.stderr | 2 +- tests/ui/type/pattern_types/nested.rs | 4 + tests/ui/type/pattern_types/nested.stderr | 52 +++++++++--- .../pattern_types/pattern_type_mismatch.rs | 12 +-- .../pattern_type_mismatch.stderr | 46 ++++++----- .../type/pattern_types/unimplemented_pat.rs | 8 +- .../pattern_types/unimplemented_pat.stderr | 21 ++--- 27 files changed, 311 insertions(+), 168 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index f8fb21d5cd09..d1e23bf25222 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -412,8 +412,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) { - self.visit_pat(p) + fn visit_pattern_type_pattern(&mut self, pat: &'hir hir::TyPat<'hir>) { + self.insert(pat.span, pat.hir_id, Node::TyPat(pat)); + + self.with_parent(pat.hir_id, |this| { + intravisit::walk_ty_pat(this, pat); + }); } fn visit_precise_capturing_arg( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 893da9308553..8728af9997a1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1377,7 +1377,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } } - TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)), + TyKind::Pat(ty, pat) => { + hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat)) + } TyKind::MacCall(_) => { span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now") } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index cde8ddbfe03c..57f15f99760a 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -4,10 +4,10 @@ use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; -use rustc_hir::def::Res; +use rustc_hir::def::{DefKind, Res}; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; -use rustc_span::{Ident, Span}; +use rustc_span::{Ident, Span, kw}; use super::errors::{ ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding, @@ -429,4 +429,80 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind }) } + + pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> { + self.arena.alloc(self.lower_ty_pat_mut(pattern)) + } + + fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> { + // loop here to avoid recursion + let pat_hir_id = self.lower_node_id(pattern.id); + let node = loop { + match &pattern.kind { + PatKind::Range(e1, e2, Spanned { node: end, .. }) => { + let mut lower_expr = |e: &Expr| -> &_ { + let kind = if let ExprKind::Path(qself, path) = &e.kind { + hir::ConstArgKind::Path(self.lower_qpath( + e.id, + qself, + path, + ParamMode::Optional, + AllowReturnTypeNotation::No, + ImplTraitContext::Disallowed(ImplTraitPosition::Path), + None, + )) + } else { + let node_id = self.next_node_id(); + let def_id = self.create_def( + self.current_hir_id_owner.def_id, + node_id, + kw::Empty, + DefKind::AnonConst, + e.span, + ); + let hir_id = self.lower_node_id(node_id); + let ac = self.arena.alloc(hir::AnonConst { + def_id, + hir_id, + body: self.lower_const_body(pattern.span, Some(e)), + span: self.lower_span(pattern.span), + }); + hir::ConstArgKind::Anon(ac) + }; + self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind }) + }; + break hir::TyPatKind::Range( + e1.as_deref().map(|e| lower_expr(e)), + e2.as_deref().map(|e| lower_expr(e)), + self.lower_range_end(end, e2.is_some()), + ); + } + // return inner to be processed in next loop + PatKind::Paren(inner) => pattern = inner, + PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), + PatKind::Err(guar) => break hir::TyPatKind::Err(*guar), + PatKind::Deref(..) + | PatKind::Box(..) + | PatKind::Or(..) + | PatKind::Struct(..) + | PatKind::TupleStruct(..) + | PatKind::Tuple(..) + | PatKind::Ref(..) + | PatKind::Expr(..) + | PatKind::Guard(..) + | PatKind::Slice(_) + | PatKind::Ident(..) + | PatKind::Path(..) + | PatKind::Wild + | PatKind::Never + | PatKind::Rest => { + break hir::TyPatKind::Err( + self.dcx().span_err(pattern.span, "pattern not supported in pattern types"), + ); + } + } + }; + + hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) } + } } diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 9ace486fa56f..576b1c76823f 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -101,6 +101,10 @@ impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> { s.s.space(); s.synth_comment(format!("pat hir_id: {}", pat.hir_id)); } + pprust_hir::AnnNode::TyPat(pat) => { + s.s.space(); + s.synth_comment(format!("ty pat hir_id: {}", pat.hir_id)); + } pprust_hir::AnnNode::Arm(arm) => { s.s.space(); s.synth_comment(format!("arm hir_id: {}", arm.hir_id)); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index af2f86b67e00..4113c7ed4bbe 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1418,6 +1418,14 @@ impl<'hir> Block<'hir> { } } +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct TyPat<'hir> { + #[stable_hasher(ignore)] + pub hir_id: HirId, + pub kind: TyPatKind<'hir>, + pub span: Span, +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Pat<'hir> { #[stable_hasher(ignore)] @@ -1591,6 +1599,15 @@ pub enum PatExprKind<'hir> { Path(QPath<'hir>), } +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub enum TyPatKind<'hir> { + /// A range pattern (e.g., `1..=2` or `1..2`). + Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd), + + /// A placeholder for a pattern that wasn't well formed in some way. + Err(ErrorGuaranteed), +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { /// Represents a wildcard pattern (i.e., `_`). @@ -3345,7 +3362,7 @@ pub enum TyKind<'hir, Unambig = ()> { /// Placeholder for a type that has failed to be defined. Err(rustc_span::ErrorGuaranteed), /// Pattern types (`pattern_type!(u32 is 1..)`) - Pat(&'hir Ty<'hir>, &'hir Pat<'hir>), + Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>), /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. /// @@ -4331,6 +4348,7 @@ pub enum Node<'hir> { AssocItemConstraint(&'hir AssocItemConstraint<'hir>), TraitRef(&'hir TraitRef<'hir>), OpaqueTy(&'hir OpaqueTy<'hir>), + TyPat(&'hir TyPat<'hir>), Pat(&'hir Pat<'hir>), PatField(&'hir PatField<'hir>), /// Needed as its own node with its own HirId for tracking @@ -4393,6 +4411,7 @@ impl<'hir> Node<'hir> { | Node::Block(..) | Node::Ctor(..) | Node::Pat(..) + | Node::TyPat(..) | Node::PatExpr(..) | Node::Arm(..) | Node::LetStmt(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 31764ab12094..6519552d6046 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -393,10 +393,8 @@ pub trait Visitor<'v>: Sized { fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result { walk_expr_field(self, field) } - fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) { - // Do nothing. Only a few visitors need to know the details of the pattern type, - // and they opt into it. All other visitors will just choke on our fake patterns - // because they aren't in a body. + fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result { + walk_ty_pat(self, p) } fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result { walk_generic_param(self, p) @@ -702,6 +700,18 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res visitor.visit_expr(arm.body) } +pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result { + try_visit!(visitor.visit_id(pattern.hir_id)); + match pattern.kind { + TyPatKind::Range(lower_bound, upper_bound, _) => { + visit_opt!(visitor, visit_const_arg_unambig, lower_bound); + visit_opt!(visitor, visit_const_arg_unambig, upper_bound); + } + TyPatKind::Err(_) => (), + } + V::Result::output() +} + pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result { try_visit!(visitor.visit_id(pattern.hir_id)); match pattern.kind { diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a4b5a87361ef..c28c1afcfe66 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -436,9 +436,6 @@ hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a t hir_analysis_parenthesized_fn_trait_expansion = parenthesized trait syntax expands to `{$expanded_type}` -hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end -hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types - .label = this type is the same as the inner type without a pattern hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index d67b9d335960..76006354717e 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -831,8 +831,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::Pat<'tcx>) { - intravisit::walk_pat(self, p) + fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) { + intravisit::walk_ty_pat(self, p) } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 348d4d708b57..4e12db190fd0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -18,9 +18,10 @@ use crate::hir_ty_lowering::HirTyLowerer; mod opaque; -fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { +fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { use hir::*; use rustc_middle::ty::Ty; + let tcx = icx.tcx; let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); @@ -54,7 +55,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { hir_id: arg_hir_id, kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }), .. - }) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span), + }) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span), // Anon consts outside the type system. Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) @@ -138,10 +139,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } } -fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { +fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> { use hir::*; use rustc_middle::ty::Ty; + let tcx = icx.tcx; + match tcx.parent_hir_node(arg_hir_id) { // Array length const arguments do not have `type_of` fed as there is never a corresponding // generic parameter definition. @@ -149,7 +152,15 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) if constant.hir_id == arg_hir_id => { - return tcx.types.usize; + tcx.types.usize + } + + Node::TyPat(pat) => { + let hir::TyKind::Pat(ty, p) = tcx.parent_hir_node(pat.hir_id).expect_ty().kind else { + bug!() + }; + assert_eq!(p.hir_id, pat.hir_id); + icx.lower_ty(ty) } // This is not a `bug!` as const arguments in path segments that did not resolve to anything @@ -344,7 +355,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ tcx.typeck(def_id).node_type(hir_id) } - Node::AnonConst(_) => anon_const_type_of(tcx, def_id), + Node::AnonConst(_) => anon_const_type_of(&icx, def_id), Node::ConstBlock(_) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id()); diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 1dcea5d03353..9769be302264 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1605,13 +1605,6 @@ pub(crate) struct OpaqueCapturesHigherRankedLifetime { pub bad_place: &'static str, } -#[derive(Diagnostic)] -#[diag(hir_analysis_pattern_type_non_const_range)] -pub(crate) struct NonConstRange { - #[primary_span] - pub span: Span, -} - #[derive(Subdiagnostic)] pub(crate) enum InvalidReceiverTyHint { #[note(hir_analysis_invalid_receiver_ty_help_weak_note)] diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs index 272edbe841b9..ec7b3aaa1c14 100644 --- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs +++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs @@ -2,13 +2,6 @@ use rustc_macros::Diagnostic; use rustc_middle::ty::Ty; use rustc_span::Span; -#[derive(Diagnostic)] -#[diag(hir_analysis_pattern_type_wild_pat)] -pub(crate) struct WildPatTy { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_invalid_base_type)] pub(crate) struct InvalidBaseType<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5813fdeae764..079e89216279 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,7 +53,7 @@ use tracing::{debug, instrument}; use crate::bounds::Bounds; use crate::check::check_abi_fn_ptr; -use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, WildPatTy}; +use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; use crate::middle::resolve_bound_vars as rbv; @@ -2435,11 +2435,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let ty_span = ty.span; let ty = self.lower_ty(ty); let pat_ty = match pat.kind { - hir::PatKind::Wild => { - let err = self.dcx().emit_err(WildPatTy { span: pat.span }); - Ty::new_error(tcx, err) - } - hir::PatKind::Range(start, end, include_end) => { + hir::TyPatKind::Range(start, end, include_end) => { let ty = match ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Char => ty, _ => Ty::new_error( @@ -2452,54 +2448,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }), ), }; - let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> { - let (c, c_ty) = match expr.kind { - hir::PatExprKind::Lit { lit, negated } => { - let lit_input = - LitToConstInput { lit: &lit.node, ty, neg: negated }; - let ct = tcx.lit_to_const(lit_input); - (ct, ty) - } - - hir::PatExprKind::Path(hir::QPath::Resolved( - _, - path @ &hir::Path { - res: Res::Def(DefKind::ConstParam, def_id), - .. - }, - )) => { - match self.prohibit_generic_args( - path.segments.iter(), - GenericsArgsErrExtend::Param(def_id), - ) { - Ok(()) => { - let ty = tcx - .type_of(def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"); - let ct = self.lower_const_param(def_id, expr.hir_id); - (ct, ty) - } - Err(guar) => ( - ty::Const::new_error(tcx, guar), - Ty::new_error(tcx, guar), - ), - } - } - - _ => { - let err = tcx - .dcx() - .emit_err(crate::errors::NonConstRange { span: expr.span }); - (ty::Const::new_error(tcx, err), Ty::new_error(tcx, err)) - } - }; - self.record_ty(expr.hir_id, c_ty, expr.span); - c - }; - - let start = start.map(expr_to_const); - let end = end.map(expr_to_const); + let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)); + let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)); let include_end = match include_end { hir::RangeEnd::Included => true, @@ -2509,12 +2459,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end }); Ty::new_pat(tcx, ty, pat) } - hir::PatKind::Err(e) => Ty::new_error(tcx, e), - _ => Ty::new_error_with_message( - tcx, - pat.span, - format!("unsupported pattern for pattern type: {pat:#?}"), - ), + hir::TyPatKind::Err(e) => Ty::new_error(tcx, e), }; self.record_ty(pat.hir_id, ty, pat.span); pat_ty diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a91afa51230d..3b163d0bc205 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -18,7 +18,7 @@ use rustc_ast_pretty::pprust::state::MacHeader; use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_hir::{ BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind, - HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, + HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TyPatKind, }; use rustc_span::source_map::SourceMap; use rustc_span::{FileName, Ident, Span, Symbol, kw}; @@ -35,6 +35,7 @@ pub enum AnnNode<'a> { SubItem(HirId), Expr(&'a hir::Expr<'a>), Pat(&'a hir::Pat<'a>), + TyPat(&'a hir::TyPat<'a>), Arm(&'a hir::Arm<'a>), } @@ -198,6 +199,7 @@ impl<'a> State<'a> { Node::TraitRef(a) => self.print_trait_ref(a), Node::OpaqueTy(o) => self.print_opaque_ty(o), Node::Pat(a) => self.print_pat(a), + Node::TyPat(a) => self.print_ty_pat(a), Node::PatField(a) => self.print_patfield(a), Node::PatExpr(a) => self.print_pat_expr(a), Node::Arm(a) => self.print_arm(a), @@ -224,6 +226,16 @@ impl<'a> State<'a> { Node::Err(_) => self.word("/*ERROR*/"), } } + + fn print_generic_arg(&mut self, generic_arg: &GenericArg<'_>, elide_lifetimes: bool) { + match generic_arg { + GenericArg::Lifetime(lt) if !elide_lifetimes => self.print_lifetime(lt), + GenericArg::Lifetime(_) => {} + GenericArg::Type(ty) => self.print_type(ty.as_unambig_ty()), + GenericArg::Const(ct) => self.print_const_arg(ct.as_unambig_ct()), + GenericArg::Infer(_inf) => self.word("_"), + } + } } impl std::ops::Deref for State<'_> { @@ -448,7 +460,7 @@ impl<'a> State<'a> { hir::TyKind::Pat(ty, pat) => { self.print_type(ty); self.word(" is "); - self.print_pat(pat); + self.print_ty_pat(pat); } } self.end() @@ -1797,13 +1809,7 @@ impl<'a> State<'a> { if nonelided_generic_args { start_or_comma(self); self.commasep(Inconsistent, generic_args.args, |s, generic_arg| { - match generic_arg { - GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), - GenericArg::Lifetime(_) => {} - GenericArg::Type(ty) => s.print_type(ty.as_unambig_ty()), - GenericArg::Const(ct) => s.print_const_arg(ct.as_unambig_ct()), - GenericArg::Infer(_inf) => s.word("_"), - } + s.print_generic_arg(generic_arg, elide_lifetimes) }); } @@ -1864,6 +1870,33 @@ impl<'a> State<'a> { } } + fn print_ty_pat(&mut self, pat: &hir::TyPat<'_>) { + self.maybe_print_comment(pat.span.lo()); + self.ann.pre(self, AnnNode::TyPat(pat)); + // Pat isn't normalized, but the beauty of it + // is that it doesn't matter + match pat.kind { + TyPatKind::Range(begin, end, end_kind) => { + if let Some(expr) = begin { + self.print_const_arg(expr); + } + match end_kind { + RangeEnd::Included => self.word("..."), + RangeEnd::Excluded => self.word(".."), + } + if let Some(expr) = end { + self.print_const_arg(expr); + } + } + TyPatKind::Err(_) => { + self.popen(); + self.word("/*ERROR*/"); + self.pclose(); + } + } + self.ann.post(self, AnnNode::TyPat(pat)) + } + fn print_pat(&mut self, pat: &hir::Pat<'_>) { self.maybe_print_comment(pat.span.lo()); self.ann.pre(self, AnnNode::Pat(pat)); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a519e177fbcc..838cd1e03f98 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => true, - hir::Node::Pat(_) => { + hir::Node::TyPat(_) | hir::Node::Pat(_) => { self.dcx().span_delayed_bug(expr.span, "place expr not allowed in pattern"); true } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 926760b84aae..4df4624971df 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -937,6 +937,7 @@ impl<'hir> Map<'hir> { Node::TraitRef(tr) => tr.path.span, Node::OpaqueTy(op) => op.span, Node::Pat(pat) => pat.span, + Node::TyPat(pat) => pat.span, Node::PatField(field) => field.span, Node::PatExpr(lit) => lit.span, Node::Arm(arm) => arm.span, @@ -1212,6 +1213,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { Node::TraitRef(_) => node_str("trait ref"), Node::OpaqueTy(_) => node_str("opaque type"), Node::Pat(_) => node_str("pat"), + Node::TyPat(_) => node_str("pat ty"), Node::PatField(_) => node_str("pattern field"), Node::PatExpr(_) => node_str("pattern literal"), Node::Param(_) => node_str("param"), diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index f6b70d9389bb..74038b24dccd 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -162,7 +162,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i)); } - fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) { - self.visit_pat(p) + fn visit_pattern_type_pattern(&mut self, p: &'hir hir::TyPat<'hir>) { + intravisit::walk_ty_pat(self, p) } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index d0eb5318e645..4bbf28115a68 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -10,7 +10,7 @@ use rustc_hir::{ AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime, LifetimeName, Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, - TraitBoundModifiers, Ty, TyKind, + TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::LateContext; @@ -1102,6 +1102,22 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } + pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) { + std::mem::discriminant(&pat.kind).hash(&mut self.s); + match pat.kind { + TyPatKind::Range(s, e, i) => { + if let Some(s) = s { + self.hash_const_arg(s); + } + if let Some(e) = e { + self.hash_const_arg(e); + } + std::mem::discriminant(&i).hash(&mut self.s); + }, + TyPatKind::Err(_) => {}, + } + } + pub fn hash_pat(&mut self, pat: &Pat<'_>) { std::mem::discriminant(&pat.kind).hash(&mut self.s); match pat.kind { @@ -1247,7 +1263,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, TyKind::Pat(ty, pat) => { self.hash_ty(ty); - self.hash_pat(pat); + self.hash_ty_pat(pat); }, TyKind::Ptr(mut_ty) => { self.hash_ty(mut_ty.ty); diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index c5f8b2764ecb..05e308de7b1e 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -6,5 +6,6 @@ type Pat = //~^ ERROR type and const arguments are not allowed on const parameter `START` //~| ERROR generic arguments are not allowed on const parameter `END` //~| ERROR associated item constraints are not allowed here +//~| ERROR `_` is not allowed within types on item signatures for type aliases fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index f31809bf397c..c4ba89de3f36 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -32,7 +32,13 @@ error[E0229]: associated item constraints are not allowed here LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); | ^^^^^^^^^^ associated item constraint not allowed here -error: aborting due to 3 previous errors +error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases + --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 + | +LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); + | ^ not allowed in type signatures -Some errors have detailed explanations: E0109, E0229. +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0109, E0121, E0229. For more information about an error, try `rustc --explain E0109`. diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs index 6cb2a0f1f8e7..549b0d11dd18 100644 --- a/tests/ui/type/pattern_types/bad_pat.rs +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -8,6 +8,6 @@ type NonNullU32_2 = pattern_type!(u32 is 1..=); type Positive2 = pattern_type!(i32 is 0..=); //~^ ERROR: inclusive range with no end type Wild = pattern_type!(() is _); -//~^ ERROR: wildcard patterns are not permitted for pattern types +//~^ ERROR: pattern not supported in pattern types fn main() {} diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index c857cc3c3add..d2a5a20bf89b 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -24,7 +24,7 @@ LL - type Positive2 = pattern_type!(i32 is 0..=); LL + type Positive2 = pattern_type!(i32 is 0..); | -error: wildcard patterns are not permitted for pattern types +error: pattern not supported in pattern types --> $DIR/bad_pat.rs:10:33 | LL | type Wild = pattern_type!(() is _); diff --git a/tests/ui/type/pattern_types/nested.rs b/tests/ui/type/pattern_types/nested.rs index 519fb3f05b48..9ca9c7923ded 100644 --- a/tests/ui/type/pattern_types/nested.rs +++ b/tests/ui/type/pattern_types/nested.rs @@ -9,16 +9,20 @@ use std::pat::pattern_type; // or still validate correctly. const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: mismatched types // We want to get the most narrowest version that a pattern could be const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: mismatched types const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: mismatched types const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); //~^ ERROR: not a valid base type for range patterns +//~| ERROR: mismatched types const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); //~^ ERROR: not a valid base type for range patterns diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr index 99d3979e98c4..b753b0a9c9ba 100644 --- a/tests/ui/type/pattern_types/nested.stderr +++ b/tests/ui/type/pattern_types/nested.stderr @@ -11,52 +11,86 @@ LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!( | ^^^ error: `(i32) is 1..=` is not a valid base type for range patterns - --> $DIR/nested.rs:14:35 + --> $DIR/nested.rs:15:35 | LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: range patterns only support integers - --> $DIR/nested.rs:14:64 + --> $DIR/nested.rs:15:64 | LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); | ^^^^^ error: `(i32) is 1..=` is not a valid base type for range patterns - --> $DIR/nested.rs:17:35 + --> $DIR/nested.rs:19:35 | LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: range patterns only support integers - --> $DIR/nested.rs:17:64 + --> $DIR/nested.rs:19:64 | LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); | ^^^ error: `()` is not a valid base type for range patterns - --> $DIR/nested.rs:20:35 + --> $DIR/nested.rs:23:35 | LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); | ^^ | note: range patterns only support integers - --> $DIR/nested.rs:20:41 + --> $DIR/nested.rs:23:41 | LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); | ^^^ error: `f32` is not a valid base type for range patterns - --> $DIR/nested.rs:23:35 + --> $DIR/nested.rs:27:35 | LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); | ^^^ | note: range patterns only support integers - --> $DIR/nested.rs:23:42 + --> $DIR/nested.rs:27:42 | LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!(); | ^^^^^^^^^^ -error: aborting due to 5 previous errors +error[E0308]: mismatched types + --> $DIR/nested.rs:10:63 + | +LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(); + | ^ expected `(u32) is 1..=`, found integer + | + = note: expected pattern type `(u32) is 1..=` + found type `{integer}` +error[E0308]: mismatched types + --> $DIR/nested.rs:15:67 + | +LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!(); + | ^^ expected `(i32) is 1..=`, found integer + | + = note: expected pattern type `(i32) is 1..=` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/nested.rs:19:66 + | +LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!(); + | ^ expected `(i32) is 1..=`, found integer + | + = note: expected pattern type `(i32) is 1..=` + found type `{integer}` + +error[E0308]: mismatched types + --> $DIR/nested.rs:23:43 + | +LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!(); + | ^ expected `()`, found integer + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.rs b/tests/ui/type/pattern_types/pattern_type_mismatch.rs index 8d375d7932bc..0c88f27d8368 100644 --- a/tests/ui/type/pattern_types/pattern_type_mismatch.rs +++ b/tests/ui/type/pattern_types/pattern_type_mismatch.rs @@ -1,20 +1,16 @@ //! Check that pattern types patterns must be of the type of the base type -//@ known-bug: unknown -//@ failure-status: 101 -//@ normalize-stderr: "note: .*\n\n" -> "" -//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" -//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@ normalize-stderr: "(delayed at compiler/rustc_mir_transform/src/lib.rs:)\d+:\d+" -> "$1:LL:CC" -//@ rustc-env:RUST_BACKTRACE=0 - #![feature(pattern_types)] #![feature(pattern_type_macro)] use std::pat::pattern_type; const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); +//~^ ERROR: mismatched types +//~| ERROR: mismatched types const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); +//~^ ERROR: mismatched types +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.stderr b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr index ee413133ab31..19b0c1059c86 100644 --- a/tests/ui/type/pattern_types/pattern_type_mismatch.stderr +++ b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr @@ -1,31 +1,37 @@ -error: internal compiler error: ty::ConstKind::Error constructed but no error reported - | - = error: internal compiler error: ty::ConstKind::Error constructed but no error reported - | - = note: delayed at compiler/rustc_mir_build/src/thir/constant.rs:72:21 - disabled backtrace - = error: internal compiler error: mir_const_qualif: MIR had errors - --> $DIR/pattern_type_mismatch.rs:16:1 +error[E0308]: mismatched types + --> $DIR/pattern_type_mismatch.rs:8:41 | LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ expected `u8`, found `char` | -note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace - --> $DIR/pattern_type_mismatch.rs:16:1 +help: if you meant to write a byte literal, prefix with `b` + | +LL | const BAD_NESTING4: pattern_type!(u8 is b'a'..='a') = todo!(); + | ~~~~ + +error[E0308]: mismatched types + --> $DIR/pattern_type_mismatch.rs:8:47 | LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ expected `u8`, found `char` + | +help: if you meant to write a byte literal, prefix with `b` + | +LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..=b'a') = todo!(); + | ~~~~ -error: internal compiler error: mir_const_qualif: MIR had errors - --> $DIR/pattern_type_mismatch.rs:18:1 +error[E0308]: mismatched types + --> $DIR/pattern_type_mismatch.rs:12:43 | LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace - --> $DIR/pattern_type_mismatch.rs:18:1 + | ^ expected `char`, found `u8` + +error[E0308]: mismatched types + --> $DIR/pattern_type_mismatch.rs:12:47 | LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ expected `char`, found `u8` -query stack during panic: -end of query stack +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type/pattern_types/unimplemented_pat.rs b/tests/ui/type/pattern_types/unimplemented_pat.rs index b2398cec7c9b..44851ec1a104 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.rs +++ b/tests/ui/type/pattern_types/unimplemented_pat.rs @@ -1,14 +1,14 @@ //! This test ensures we do not ICE for unimplemented -//! patterns unless the feature gate is enabled. +//! patterns even if the feature gate is enabled. -#![feature(pattern_type_macro)] +#![feature(pattern_type_macro, pattern_types)] use std::pat::pattern_type; type Always = pattern_type!(Option is Some(_)); -//~^ ERROR: pattern types are unstable +//~^ ERROR: pattern not supported type Binding = pattern_type!(Option is x); -//~^ ERROR: pattern types are unstable +//~^ ERROR: pattern not supported fn main() {} diff --git a/tests/ui/type/pattern_types/unimplemented_pat.stderr b/tests/ui/type/pattern_types/unimplemented_pat.stderr index 7b0f9cbaa6a9..a1e55ed02c45 100644 --- a/tests/ui/type/pattern_types/unimplemented_pat.stderr +++ b/tests/ui/type/pattern_types/unimplemented_pat.stderr @@ -1,23 +1,14 @@ -error[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:8:15 +error: pattern not supported in pattern types + --> $DIR/unimplemented_pat.rs:8:44 | LL | type Always = pattern_type!(Option is Some(_)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #123646 for more information - = help: add `#![feature(pattern_types)]` 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[E0658]: pattern types are unstable - --> $DIR/unimplemented_pat.rs:11:16 +error: pattern not supported in pattern types + --> $DIR/unimplemented_pat.rs:11:45 | LL | type Binding = pattern_type!(Option is x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #123646 for more information - = help: add `#![feature(pattern_types)]` 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 2 previous errors -For more information about this error, try `rustc --explain E0658`. From 49ea67aa91642708435cb344d0c32fc839e1c4f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Feb 2025 12:05:23 +0100 Subject: [PATCH 37/68] std::fs: further simplify dirent64 handling --- library/std/src/sys/pal/unix/fs.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fdf011c19482..6c41781fe850 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -740,29 +740,27 @@ impl Iterator for ReadDir { // to `byte_offset` and thus does not require the full extent of `*entry_ptr` // to be in bounds of the same allocation, only the offset of the field // being referenced. - macro_rules! entry_field_ptr { - ($field:ident) => { - &raw const (*entry_ptr).$field - }; - } // d_name is guaranteed to be null-terminated. - let name = CStr::from_ptr(entry_field_ptr!(d_name).cast()); + let name = CStr::from_ptr((&raw const (*entry_ptr).d_name).cast()); let name_bytes = name.to_bytes(); if name_bytes == b"." || name_bytes == b".." { continue; } + // When loading from a field, we can skip the `&raw const`; `(*entry_ptr).d_ino` as + // a value expression will do the right thing: `byte_offset` to the field and then + // only access those bytes. #[cfg(not(target_os = "vita"))] let entry = dirent64_min { - d_ino: *entry_field_ptr!(d_ino) as u64, + d_ino: (*entry_ptr).d_ino as u64, #[cfg(not(any( target_os = "solaris", target_os = "illumos", target_os = "aix", target_os = "nto", )))] - d_type: *entry_field_ptr!(d_type) as u8, + d_type: (*entry_ptr).d_type as u8, }; #[cfg(target_os = "vita")] From 37c77defb4fa327abc7377f5f6e8fc9692afe52a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 3 Feb 2025 16:37:59 +0100 Subject: [PATCH 38/68] For NonZero impl macros, give unsigned impls access to the corresponding signed type There was a macro parameter giving signed impls access to the corresponding unsigned type, but not the other way around. This will allow implementing methods converting in both directions. --- library/core/src/num/nonzero.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 61e83ebfad7d..3becbc9bade3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -474,6 +474,7 @@ macro_rules! nonzero_integer { #[$stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, + SignedPrimitive = $Sint:ty, UnsignedPrimitive = $Uint:ty, // Used in doc comments. @@ -905,6 +906,7 @@ macro_rules! nonzero_integer { nonzero_integer_signedness_dependent_methods! { Primitive = $signedness $Int, + SignedPrimitive = $Sint, UnsignedPrimitive = $Uint, } @@ -1128,6 +1130,7 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = unsigned $Int:ident, + SignedPrimitive = $Sint:ident, rot = $rot:literal, rot_op = $rot_op:literal, rot_result = $rot_result:literal, @@ -1140,6 +1143,7 @@ macro_rules! nonzero_integer { #[stable(feature = "nonzero", since = "1.28.0")] Self = $Ty, Primitive = unsigned $Int, + SignedPrimitive = $Sint, UnsignedPrimitive = $Int, rot = $rot, rot_op = $rot_op, @@ -1154,7 +1158,7 @@ macro_rules! nonzero_integer { ( Self = $Ty:ident, Primitive = signed $Int:ident, - UnsignedPrimitive = $UInt:ident, + UnsignedPrimitive = $Uint:ident, rot = $rot:literal, rot_op = $rot_op:literal, rot_result = $rot_result:literal, @@ -1166,7 +1170,8 @@ macro_rules! nonzero_integer { #[stable(feature = "signed_nonzero", since = "1.34.0")] Self = $Ty, Primitive = signed $Int, - UnsignedPrimitive = $UInt, + SignedPrimitive = $Int, + UnsignedPrimitive = $Uint, rot = $rot, rot_op = $rot_op, rot_result = $rot_result, @@ -1286,6 +1291,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // Associated items for unsigned nonzero types only. ( Primitive = unsigned $Int:ident, + SignedPrimitive = $Sint:ty, UnsignedPrimitive = $Uint:ty, ) => { /// The smallest value that can be represented by this non-zero @@ -1625,6 +1631,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // Associated items for signed nonzero types only. ( Primitive = signed $Int:ident, + SignedPrimitive = $Sint:ty, UnsignedPrimitive = $Uint:ty, ) => { /// The smallest value that can be represented by this non-zero @@ -2041,6 +2048,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods { nonzero_integer! { Self = NonZeroU8, Primitive = unsigned u8, + SignedPrimitive = i8, rot = 2, rot_op = "0x82", rot_result = "0xa", @@ -2052,6 +2060,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroU16, Primitive = unsigned u16, + SignedPrimitive = i16, rot = 4, rot_op = "0xa003", rot_result = "0x3a", @@ -2063,6 +2072,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroU32, Primitive = unsigned u32, + SignedPrimitive = i32, rot = 8, rot_op = "0x10000b3", rot_result = "0xb301", @@ -2074,6 +2084,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroU64, Primitive = unsigned u64, + SignedPrimitive = i64, rot = 12, rot_op = "0xaa00000000006e1", rot_result = "0x6e10aa", @@ -2085,6 +2096,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroU128, Primitive = unsigned u128, + SignedPrimitive = i128, rot = 16, rot_op = "0x13f40000000000000000000000004f76", rot_result = "0x4f7613f4", @@ -2097,6 +2109,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + SignedPrimitive = isize, rot = 4, rot_op = "0xa003", rot_result = "0x3a", @@ -2109,6 +2122,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + SignedPrimitive = isize, rot = 8, rot_op = "0x10000b3", rot_result = "0xb301", @@ -2121,6 +2135,7 @@ nonzero_integer! { nonzero_integer! { Self = NonZeroUsize, Primitive = unsigned usize, + SignedPrimitive = isize, rot = 12, rot_op = "0xaa00000000006e1", rot_result = "0x6e10aa", From 7dfc786df1360319e9817485f767a815a9cff3a7 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 25 Dec 2024 22:24:30 -0500 Subject: [PATCH 39/68] Enable more tests on Windows --- tests/codegen/debug-column.rs | 2 +- tests/codegen/force-no-unwind-tables.rs | 2 +- tests/codegen/thread-local.rs | 2 +- tests/crashes/132981.rs | 4 ++++ .../relative-path-include-bytes-132203.rs | 2 +- tests/ui-fulldeps/stable-mir/check_abi.rs | 1 - .../ui-fulldeps/stable-mir/check_allocation.rs | 1 - .../ui-fulldeps/stable-mir/check_attribute.rs | 1 - tests/ui-fulldeps/stable-mir/check_binop.rs | 1 - .../ui-fulldeps/stable-mir/check_crate_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_def_ty.rs | 1 - tests/ui-fulldeps/stable-mir/check_defs.rs | 1 - tests/ui-fulldeps/stable-mir/check_foreign.rs | 1 - tests/ui-fulldeps/stable-mir/check_instance.rs | 1 - .../ui-fulldeps/stable-mir/check_intrinsics.rs | 1 - .../ui-fulldeps/stable-mir/check_item_kind.rs | 1 - .../stable-mir/check_normalization.rs | 1 - .../stable-mir/check_trait_queries.rs | 1 - .../ui-fulldeps/stable-mir/check_transform.rs | 1 - tests/ui-fulldeps/stable-mir/check_ty_fold.rs | 1 - .../stable-mir/compilation-result.rs | 1 - tests/ui-fulldeps/stable-mir/crate-info.rs | 1 - tests/ui-fulldeps/stable-mir/projections.rs | 1 - tests/ui-fulldeps/stable-mir/smir_internal.rs | 1 - tests/ui-fulldeps/stable-mir/smir_serde.rs | 1 - tests/ui-fulldeps/stable-mir/smir_visitor.rs | 1 - tests/ui/abi/abi-sysv64-arg-passing.rs | 3 ++- tests/ui/abi/large-byval-align.rs | 1 - .../feature-gate-cfg-target-thread-local.rs | 2 +- tests/ui/inference/issue-71584.rs | 2 +- ...age-attr-does-not-panic-llvm-issue-33992.rs | 3 ++- .../propagate-generic-issue-18804/main.rs | 1 - tests/ui/logging-only-prints-once.rs | 1 - tests/ui/lto/weak-works.rs | 3 ++- tests/ui/parser/mod_file_not_exist.rs | 2 -- tests/ui/parser/mod_file_not_exist.stderr | 4 ++-- .../suggestions/missing-lifetime-specifier.rs | 1 - .../missing-lifetime-specifier.stderr | 18 +++++++++--------- .../ui/threads-sendsync/spawning-with-debug.rs | 1 - .../thread-local-extern-static.rs | 2 +- tests/ui/traits/issue-77982.rs | 5 +++-- tests/ui/traits/issue-77982.stderr | 14 +++++++------- tests/ui/typeck/issue-43189.rs | 1 - tests/ui/typeck/issue-43189.stderr | 2 +- tests/ui/typeck/issue-46112.rs | 1 - tests/ui/typeck/issue-46112.stderr | 4 ++-- 46 files changed, 41 insertions(+), 63 deletions(-) diff --git a/tests/codegen/debug-column.rs b/tests/codegen/debug-column.rs index d14a5c29142e..2aa0a8a864ca 100644 --- a/tests/codegen/debug-column.rs +++ b/tests/codegen/debug-column.rs @@ -1,6 +1,6 @@ // Verify that debuginfo column numbers are 1-based byte offsets. // -//@ ignore-windows +//@ ignore-msvc //@ compile-flags: -C debuginfo=2 #[rustfmt::skip] diff --git a/tests/codegen/force-no-unwind-tables.rs b/tests/codegen/force-no-unwind-tables.rs index e823bedac0f6..1de5e0858e0b 100644 --- a/tests/codegen/force-no-unwind-tables.rs +++ b/tests/codegen/force-no-unwind-tables.rs @@ -1,5 +1,5 @@ //@ compile-flags: -C no-prepopulate-passes -C panic=abort -C force-unwind-tables=n -//@ ignore-windows +//@ ignore-windows: unwind tables are required for panics on Windows #![crate_type = "lib"] diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs index 2ee15811cc3d..3cd81652f5ac 100644 --- a/tests/codegen/thread-local.rs +++ b/tests/codegen/thread-local.rs @@ -1,6 +1,6 @@ //@ compile-flags: -O //@ aux-build:thread_local_aux.rs -//@ ignore-windows FIXME(#84933) +//@ ignore-windows FIXME(#134939) //@ ignore-wasm globals are used instead of thread locals //@ ignore-emscripten globals are used instead of thread locals //@ ignore-android does not use #[thread_local] diff --git a/tests/crashes/132981.rs b/tests/crashes/132981.rs index 8ff4fa36fd07..916c15592404 100644 --- a/tests/crashes/132981.rs +++ b/tests/crashes/132981.rs @@ -2,6 +2,10 @@ //@compile-flags: -Clink-dead-code=true --crate-type lib //@ only-x86_64 //@ ignore-windows +// The set of targets this crashes on is really fiddly, because it is deep in our ABI logic. It +// crashes on x86_64-unknown-linux-gnu, and i686-pc-windows-msvc, but not on +// x86_64-pc-windows-msvc. If you are trying to fix this crash, don't pay too much attention to the +// directives. #![feature(rust_cold_cc)] pub extern "rust-cold" fn foo(_: [usize; 3]) {} diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs index 5c9e2978e48a..6fddaa49face 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.rs @@ -1,4 +1,4 @@ -//@ ignore-windows +//@ ignore-windows different error message //@ revisions: edition2015 edition2024 //@[edition2015]edition:2015 //@[edition2015]check-fail diff --git a/tests/ui-fulldeps/stable-mir/check_abi.rs b/tests/ui-fulldeps/stable-mir/check_abi.rs index 8caf3032afc4..ef2d5b4854be 100644 --- a/tests/ui-fulldeps/stable-mir/check_abi.rs +++ b/tests/ui-fulldeps/stable-mir/check_abi.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 072c8ba6a442..c102f86a2286 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_attribute.rs b/tests/ui-fulldeps/stable-mir/check_attribute.rs index 22481e275a99..11cb63f3f8a5 100644 --- a/tests/ui-fulldeps/stable-mir/check_attribute.rs +++ b/tests/ui-fulldeps/stable-mir/check_attribute.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_binop.rs b/tests/ui-fulldeps/stable-mir/check_binop.rs index 8c44e2851084..65b3ffd27ab0 100644 --- a/tests/ui-fulldeps/stable-mir/check_binop.rs +++ b/tests/ui-fulldeps/stable-mir/check_binop.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs index ed093903381b..71cca94c34f6 100644 --- a/tests/ui-fulldeps/stable-mir/check_crate_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_crate_defs.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_def_ty.rs b/tests/ui-fulldeps/stable-mir/check_def_ty.rs index 482dbd22d5fe..37b9a83e33e7 100644 --- a/tests/ui-fulldeps/stable-mir/check_def_ty.rs +++ b/tests/ui-fulldeps/stable-mir/check_def_ty.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_defs.rs b/tests/ui-fulldeps/stable-mir/check_defs.rs index bf1f1a2ceab9..cd3d76d87601 100644 --- a/tests/ui-fulldeps/stable-mir/check_defs.rs +++ b/tests/ui-fulldeps/stable-mir/check_defs.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_foreign.rs b/tests/ui-fulldeps/stable-mir/check_foreign.rs index 4acbabbb6be1..bc3956b30908 100644 --- a/tests/ui-fulldeps/stable-mir/check_foreign.rs +++ b/tests/ui-fulldeps/stable-mir/check_foreign.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index 464350b10457..72a138f907e7 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs index 6edebaf756c5..2f772b978865 100644 --- a/tests/ui-fulldeps/stable-mir/check_intrinsics.rs +++ b/tests/ui-fulldeps/stable-mir/check_intrinsics.rs @@ -8,7 +8,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_item_kind.rs b/tests/ui-fulldeps/stable-mir/check_item_kind.rs index 23b54e6c60b3..647ce534589e 100644 --- a/tests/ui-fulldeps/stable-mir/check_item_kind.rs +++ b/tests/ui-fulldeps/stable-mir/check_item_kind.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_normalization.rs b/tests/ui-fulldeps/stable-mir/check_normalization.rs index 928173b154b4..de14202adb9c 100644 --- a/tests/ui-fulldeps/stable-mir/check_normalization.rs +++ b/tests/ui-fulldeps/stable-mir/check_normalization.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs index 304a7ce92555..23c2844d3f16 100644 --- a/tests/ui-fulldeps/stable-mir/check_trait_queries.rs +++ b/tests/ui-fulldeps/stable-mir/check_trait_queries.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/check_transform.rs b/tests/ui-fulldeps/stable-mir/check_transform.rs index bcf79c456b07..d9fc924933fa 100644 --- a/tests/ui-fulldeps/stable-mir/check_transform.rs +++ b/tests/ui-fulldeps/stable-mir/check_transform.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 #![feature(rustc_private)] #![feature(assert_matches)] diff --git a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs index e21508c9b461..9fa4929d68e2 100644 --- a/tests/ui-fulldeps/stable-mir/check_ty_fold.rs +++ b/tests/ui-fulldeps/stable-mir/check_ty_fold.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index d921de73f436..b8a9e720e546 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 53be8eb10c1e..7f0e9b50335d 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/projections.rs b/tests/ui-fulldeps/stable-mir/projections.rs index fdb7eeed1b0e..3cc71247e674 100644 --- a/tests/ui-fulldeps/stable-mir/projections.rs +++ b/tests/ui-fulldeps/stable-mir/projections.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs index 6f5478c08bf9..453e5372de4f 100644 --- a/tests/ui-fulldeps/stable-mir/smir_internal.rs +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -5,7 +5,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_serde.rs b/tests/ui-fulldeps/stable-mir/smir_serde.rs index 7dbf892f9e4b..2c74276d550c 100644 --- a/tests/ui-fulldeps/stable-mir/smir_serde.rs +++ b/tests/ui-fulldeps/stable-mir/smir_serde.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index 666000d3b070..0a6415d490e4 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -4,7 +4,6 @@ //@ ignore-stage1 //@ ignore-cross-compile //@ ignore-remote -//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ edition: 2021 #![feature(rustc_private)] diff --git a/tests/ui/abi/abi-sysv64-arg-passing.rs b/tests/ui/abi/abi-sysv64-arg-passing.rs index 04942e984a81..c18752418a1d 100644 --- a/tests/ui/abi/abi-sysv64-arg-passing.rs +++ b/tests/ui/abi/abi-sysv64-arg-passing.rs @@ -29,7 +29,8 @@ //@ ignore-aarch64 //@ ignore-windows -// note: windows is ignored as rust_test_helpers does not have the sysv64 abi on windows +// Windows is ignored because bootstrap doesn't yet know to compile rust_test_helpers with +// the sysv64 ABI on Windows. #[allow(dead_code)] #[allow(improper_ctypes)] diff --git a/tests/ui/abi/large-byval-align.rs b/tests/ui/abi/large-byval-align.rs index e39170df72b4..ddd579f264e6 100644 --- a/tests/ui/abi/large-byval-align.rs +++ b/tests/ui/abi/large-byval-align.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Copt-level=0 //@ only-x86_64 -//@ ignore-windows //@ min-llvm-version: 19 //@ build-pass diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index 3ab5a500dfdb..131a10ea03b1 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -1,4 +1,4 @@ -//@ ignore-windows +//@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows //@ aux-build:cfg-target-thread-local.rs #![feature(thread_local)] diff --git a/tests/ui/inference/issue-71584.rs b/tests/ui/inference/issue-71584.rs index 7e4d45ec4a04..61568e5467c5 100644 --- a/tests/ui/inference/issue-71584.rs +++ b/tests/ui/inference/issue-71584.rs @@ -1,4 +1,4 @@ -//@ ignore-windows different list of satisfying impls +//@ ignore-windows FIXME: We get an extra E0283 on Windows fn main() { let n: u32 = 1; let mut d: u64 = 2; diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index a169997927eb..df73eddd8d55 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-windows //@ ignore-apple //@ ignore-wasm32 common linkage not implemented right now @@ -11,9 +10,11 @@ pub static TEST2: bool = true; #[linkage = "internal"] pub static TEST3: bool = true; +#[cfg(not(target_env = "msvc"))] #[linkage = "linkonce"] pub static TEST4: bool = true; +#[cfg(not(target_env = "msvc"))] #[linkage = "linkonce_odr"] pub static TEST5: bool = true; diff --git a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs index 56a9358cce3c..8c194ec50df4 100644 --- a/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs +++ b/tests/ui/linkage-attr/propagate-generic-issue-18804/main.rs @@ -3,7 +3,6 @@ // functions. Failure results in a linker error. //@ ignore-emscripten no weak symbol support -//@ ignore-windows no extern_weak linkage //@ ignore-apple no extern_weak linkage //@ aux-build:lib.rs diff --git a/tests/ui/logging-only-prints-once.rs b/tests/ui/logging-only-prints-once.rs index 5377d5eeae2b..bb8c29694b52 100644 --- a/tests/ui/logging-only-prints-once.rs +++ b/tests/ui/logging-only-prints-once.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-windows //@ needs-threads use std::cell::Cell; diff --git a/tests/ui/lto/weak-works.rs b/tests/ui/lto/weak-works.rs index 00e10b97d60c..1ff47ca602d2 100644 --- a/tests/ui/lto/weak-works.rs +++ b/tests/ui/lto/weak-works.rs @@ -1,7 +1,8 @@ //@ run-pass //@ compile-flags: -C codegen-units=8 -Z thinlto -//@ ignore-windows +//@ ignore-i686-pc-windows-gnu +//@ ignore-x86_64-pc-windows-gnu #![feature(linkage)] diff --git a/tests/ui/parser/mod_file_not_exist.rs b/tests/ui/parser/mod_file_not_exist.rs index e7727944147e..49ce44982ab9 100644 --- a/tests/ui/parser/mod_file_not_exist.rs +++ b/tests/ui/parser/mod_file_not_exist.rs @@ -1,5 +1,3 @@ -//@ ignore-windows - mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` //~^ HELP to create the module `not_a_real_file`, create file diff --git a/tests/ui/parser/mod_file_not_exist.stderr b/tests/ui/parser/mod_file_not_exist.stderr index 40041b11c8b8..d9e4e8f31f5f 100644 --- a/tests/ui/parser/mod_file_not_exist.stderr +++ b/tests/ui/parser/mod_file_not_exist.stderr @@ -1,5 +1,5 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist.rs:3:1 + --> $DIR/mod_file_not_exist.rs:1:1 | LL | mod not_a_real_file; | ^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | mod not_a_real_file; = note: if there is a `mod not_a_real_file` elsewhere in the crate already, import it with `use crate::...` instead error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` - --> $DIR/mod_file_not_exist.rs:7:16 + --> $DIR/mod_file_not_exist.rs:5:16 | LL | assert_eq!(mod_file_aux::bar(), 10); | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux` diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index dd437fc0c0b8..a957477897d5 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,6 +1,5 @@ // The specific errors produced depend the thread-local implementation. // Run only on platforms with "fast" TLS. -//@ ignore-windows FIXME(#84933) //@ ignore-wasm globals are used instead of thread locals //@ ignore-emscripten globals are used instead of thread locals //@ ignore-android does not use #[thread_local] diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index e0b6bb872b55..1fdbf3b0c79a 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:28:44 + --> $DIR/missing-lifetime-specifier.rs:27:44 | LL | static a: RefCell>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,7 +11,7 @@ LL | static a: RefCell>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:32:44 + --> $DIR/missing-lifetime-specifier.rs:31:44 | LL | static b: RefCell>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -25,7 +25,7 @@ LL | static b: RefCell>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:47 + --> $DIR/missing-lifetime-specifier.rs:35:47 | LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -37,7 +37,7 @@ LL | static c: RefCell>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:40:44 + --> $DIR/missing-lifetime-specifier.rs:39:44 | LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -51,7 +51,7 @@ LL | static d: RefCell $DIR/missing-lifetime-specifier.rs:49:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -63,7 +63,7 @@ LL | static f: RefCell>>>> = | +++++++ error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:45:44 + --> $DIR/missing-lifetime-specifier.rs:44:44 | LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -71,7 +71,7 @@ LL | static e: RefCell>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:21:11 + --> $DIR/missing-lifetime-specifier.rs:20:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -81,7 +81,7 @@ LL | static e: RefCell>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:49:45 + --> $DIR/missing-lifetime-specifier.rs:48:45 | LL | static f: RefCell>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -89,7 +89,7 @@ LL | static f: RefCell>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:25:7 + --> $DIR/missing-lifetime-specifier.rs:24:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- diff --git a/tests/ui/threads-sendsync/spawning-with-debug.rs b/tests/ui/threads-sendsync/spawning-with-debug.rs index 90a81c1e53bc..3b7107e2dbfa 100644 --- a/tests/ui/threads-sendsync/spawning-with-debug.rs +++ b/tests/ui/threads-sendsync/spawning-with-debug.rs @@ -1,7 +1,6 @@ //@ run-pass #![allow(unused_must_use)] #![allow(unused_mut)] -//@ ignore-windows //@ exec-env:RUST_LOG=debug //@ needs-threads diff --git a/tests/ui/threads-sendsync/thread-local-extern-static.rs b/tests/ui/threads-sendsync/thread-local-extern-static.rs index ca66f8ad1d36..ce2a221ec2e4 100644 --- a/tests/ui/threads-sendsync/thread-local-extern-static.rs +++ b/tests/ui/threads-sendsync/thread-local-extern-static.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-windows +//@ ignore-windows FIXME(134939): thread_local + no_mangle doesn't work on Windows //@ aux-build:thread-local-extern-static.rs #![feature(cfg_target_thread_local, thread_local)] diff --git a/tests/ui/traits/issue-77982.rs b/tests/ui/traits/issue-77982.rs index dce25e62e468..b2a488e18e82 100644 --- a/tests/ui/traits/issue-77982.rs +++ b/tests/ui/traits/issue-77982.rs @@ -1,5 +1,6 @@ -//@ ignore-windows different list of satisfying impls -//@ ignore-arm different list of satisfying impls +//@ ignore-windows FIXME: We get an extra E0283 on Windows +//@ ignore-arm extra satisfying impls + use std::collections::HashMap; fn what() { diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr index 2b26a1b7ab15..4907a6dd17af 100644 --- a/tests/ui/traits/issue-77982.stderr +++ b/tests/ui/traits/issue-77982.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:10:10 + --> $DIR/issue-77982.rs:11:10 | LL | opts.get(opt.as_ref()); | ^^^ ------------ type must be known at this point @@ -18,7 +18,7 @@ LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:10:10 + --> $DIR/issue-77982.rs:11:10 | LL | opts.get(opt.as_ref()); | ^^^ ------ type must be known at this point @@ -36,7 +36,7 @@ LL | opts.get::(opt.as_ref()); | +++++ error[E0283]: type annotations needed - --> $DIR/issue-77982.rs:15:59 + --> $DIR/issue-77982.rs:16:59 | LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(); | --- ^^^^ @@ -56,13 +56,13 @@ LL | let ips: Vec<_> = (0..100_000).map(|_| u32::from(>::into | +++++++++++++++++++++++ ~ error[E0283]: type annotations needed for `Box<_>` - --> $DIR/issue-77982.rs:38:9 + --> $DIR/issue-77982.rs:39:9 | LL | let _ = ().foo(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `(): Foo<'_, _>` found - --> $DIR/issue-77982.rs:31:1 + --> $DIR/issue-77982.rs:32:1 | LL | impl Foo<'static, u32> for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,13 +74,13 @@ LL | let _: Box = ().foo(); | ++++++++ error[E0283]: type annotations needed for `Box<_>` - --> $DIR/issue-77982.rs:42:9 + --> $DIR/issue-77982.rs:43:9 | LL | let _ = (&()).bar(); | ^ --- type must be known at this point | note: multiple `impl`s satisfying `&(): Bar<'_, _>` found - --> $DIR/issue-77982.rs:34:1 + --> $DIR/issue-77982.rs:35:1 | LL | impl<'a> Bar<'static, u32> for &'a () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/typeck/issue-43189.rs b/tests/ui/typeck/issue-43189.rs index 9c8cc70e63a6..ee0fe15eebac 100644 --- a/tests/ui/typeck/issue-43189.rs +++ b/tests/ui/typeck/issue-43189.rs @@ -1,7 +1,6 @@ // Issue 46112: An extern crate pub re-exporting libcore was causing // paths rooted from `std` to be misrendered in the diagnostic output. -//@ ignore-windows //@ aux-build:xcrate-issue-43189-a.rs //@ aux-build:xcrate-issue-43189-b.rs diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr index 8432cbeca2a4..3cc1ba9ddfe1 100644 --- a/tests/ui/typeck/issue-43189.stderr +++ b/tests/ui/typeck/issue-43189.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope - --> $DIR/issue-43189.rs:10:8 + --> $DIR/issue-43189.rs:9:8 | LL | ().a(); | ^ method not found in `()` diff --git a/tests/ui/typeck/issue-46112.rs b/tests/ui/typeck/issue-46112.rs index 4671ddd06c83..cc8029771d6d 100644 --- a/tests/ui/typeck/issue-46112.rs +++ b/tests/ui/typeck/issue-46112.rs @@ -1,7 +1,6 @@ // Issue 46112: An extern crate pub re-exporting libcore was causing // paths rooted from `std` to be misrendered in the diagnostic output. -//@ ignore-windows //@ aux-build:xcrate-issue-46112-rexport-core.rs extern crate xcrate_issue_46112_rexport_core; diff --git a/tests/ui/typeck/issue-46112.stderr b/tests/ui/typeck/issue-46112.stderr index 16beaea75db7..9d439d10f1ed 100644 --- a/tests/ui/typeck/issue-46112.stderr +++ b/tests/ui/typeck/issue-46112.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-46112.rs:9:21 + --> $DIR/issue-46112.rs:8:21 | LL | fn main() { test(Ok(())); } | -- ^^ expected `Option<()>`, found `()` @@ -9,7 +9,7 @@ LL | fn main() { test(Ok(())); } = note: expected enum `Option<()>` found unit type `()` help: the type constructed contains `()` due to the type of the argument passed - --> $DIR/issue-46112.rs:9:18 + --> $DIR/issue-46112.rs:8:18 | LL | fn main() { test(Ok(())); } | ^^^--^ From ebeaf2e302c3c01b21e7a349190dc9b88f730e3b Mon Sep 17 00:00:00 2001 From: "Pascal S. de Kloe" Date: Wed, 8 Jan 2025 19:42:54 +0100 Subject: [PATCH 40/68] no unsafe pointer and no overflowing_literals in fmt::Display of integers --- library/core/src/fmt/num.rs | 143 +++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 68 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 683e45b35f70..7166f106b8da 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -192,7 +192,8 @@ macro_rules! impl_Debug { } // 2 digit decimal look up table -static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ +static DEC_DIGITS_LUT: &[u8; 200] = b"\ + 0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ 6061626364656667686970717273747576777879\ @@ -232,83 +233,89 @@ macro_rules! impl_Display { #[cfg(not(feature = "optimize_for_size"))] impl $unsigned { - fn _fmt(mut self, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { - const SIZE: usize = $unsigned::MAX.ilog(10) as usize + 1; - let mut buf = [MaybeUninit::::uninit(); SIZE]; - let mut curr = SIZE; - let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); - let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + fn _fmt(self, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const MAX_DEC_N: usize = $unsigned::MAX.ilog(10) as usize + 1; + // Buffer decimals for $unsigned with right alignment. + let mut buf = [MaybeUninit::::uninit(); MAX_DEC_N]; + // Count the number of bytes in buf that are not initialized. + let mut offset = buf.len(); + // Consume the least-significant decimals from a working copy. + let mut remain = self; - // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we - // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show - // that it's OK to copy into `buf_ptr`, notice that at the beginning - // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at - // each step this is kept the same as `n` is divided. Since `n` is always - // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` - // is safe to access. - unsafe { - // need at least 16 bits for the 4-characters-at-a-time to work. - #[allow(overflowing_literals)] - #[allow(unused_comparisons)] - // This block will be removed for smaller types at compile time and in the worst - // case, it will prevent to have the `10000` literal to overflow for `i8` and `u8`. - if core::mem::size_of::<$unsigned>() >= 2 { - // eagerly decode 4 characters at a time - while self >= 10000 { - let rem = (self % 10000) as usize; - self /= 10000; + // Format per four digits from the lookup table. + // Four digits need a 16-bit $unsigned or wider. + while size_of::() > 1 && remain > 999.try_into().expect("branch is not hit for types that cannot fit 999 (u8)") { + // SAFETY: All of the decimals fit in buf due to MAX_DEC_N + // and the while condition ensures at least 4 more decimals. + unsafe { core::hint::assert_unchecked(offset >= 4) } + // SAFETY: The offset counts down from its initial buf.len() + // without underflow due to the previous precondition. + unsafe { core::hint::assert_unchecked(offset <= buf.len()) } + offset -= 4; - let d1 = (rem / 100) << 1; - let d2 = (rem % 100) << 1; - curr -= 4; - - // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since - // otherwise `curr < 0`. But then `n` was originally at least `10000^10` - // which is `10^40 > 2^128 > n`. - ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(curr), 2); - ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(curr + 2), 2); - } - } - - // if we reach here numbers are <= 9999, so at most 4 chars long - let mut n = self as usize; // possibly reduce 64bit math - - // decode 2 more chars, if > 2 chars - if n >= 100 { - let d1 = (n % 100) << 1; - n /= 100; - curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); - } - - // if we reach here numbers are <= 100, so at most 2 chars long - // The biggest it can be is 99, and 99 << 1 == 198, so a `u8` is enough. - // decode last 1 or 2 chars - if n < 10 { - curr -= 1; - *buf_ptr.add(curr) = (n as u8) + b'0'; - } else { - let d1 = n << 1; - curr -= 2; - ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2); - } + // pull two pairs + let scale: Self = 1_00_00.try_into().expect("branch is not hit for types that cannot fit 1E4 (u8)"); + let quad = remain % scale; + remain /= scale; + let pair1 = (quad / 100) as usize; + let pair2 = (quad % 100) as usize; + buf[offset + 0].write(DEC_DIGITS_LUT[pair1 * 2 + 0]); + buf[offset + 1].write(DEC_DIGITS_LUT[pair1 * 2 + 1]); + buf[offset + 2].write(DEC_DIGITS_LUT[pair2 * 2 + 0]); + buf[offset + 3].write(DEC_DIGITS_LUT[pair2 * 2 + 1]); } - // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid - // UTF-8 since `DEC_DIGITS_LUT` is - let buf_slice = unsafe { - str::from_utf8_unchecked( - slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr)) + // Format per two digits from the lookup table. + if remain > 9 { + // SAFETY: All of the decimals fit in buf due to MAX_DEC_N + // and the while condition ensures at least 2 more decimals. + unsafe { core::hint::assert_unchecked(offset >= 2) } + // SAFETY: The offset counts down from its initial buf.len() + // without underflow due to the previous precondition. + unsafe { core::hint::assert_unchecked(offset <= buf.len()) } + offset -= 2; + + let pair = (remain % 100) as usize; + remain /= 100; + buf[offset + 0].write(DEC_DIGITS_LUT[pair * 2 + 0]); + buf[offset + 1].write(DEC_DIGITS_LUT[pair * 2 + 1]); + } + + // Format the last remaining digit, if any. + if remain != 0 || self == 0 { + // SAFETY: All of the decimals fit in buf due to MAX_DEC_N + // and the if condition ensures (at least) 1 more decimals. + unsafe { core::hint::assert_unchecked(offset >= 1) } + // SAFETY: The offset counts down from its initial buf.len() + // without underflow due to the previous precondition. + unsafe { core::hint::assert_unchecked(offset <= buf.len()) } + offset -= 1; + + // Either the compiler sees that remain < 10, or it prevents + // a boundary check up next. + let last = (remain & 15) as usize; + buf[offset].write(DEC_DIGITS_LUT[last * 2 + 1]); + // not used: remain = 0; + } + + // SAFETY: All buf content since offset is set. + let written = unsafe { buf.get_unchecked(offset..) }; + // SAFETY: Writes use ASCII from the lookup table exclusively. + let as_str = unsafe { + str::from_utf8_unchecked(slice::from_raw_parts( + MaybeUninit::slice_as_ptr(written), + written.len(), + )) }; - f.pad_integral(is_nonnegative, "", buf_slice) + f.pad_integral(is_nonnegative, "", as_str) } })* #[cfg(feature = "optimize_for_size")] fn $gen_name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { - const SIZE: usize = $u::MAX.ilog(10) as usize + 1; - let mut buf = [MaybeUninit::::uninit(); SIZE]; - let mut curr = buf.len(); + const MAX_DEC_N: usize = $u::MAX.ilog(10) as usize + 1; + let mut buf = [MaybeUninit::::uninit(); MAX_DEC_N]; + let mut curr = MAX_DEC_N; let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); // SAFETY: To show that it's OK to copy into `buf_ptr`, notice that at the beginning From b909c36f40035bcc0a25f8734ee6480685cba1b1 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 3 Feb 2025 07:34:47 -0500 Subject: [PATCH 41/68] Remove allocations in `FnCtxt` checks. --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 172 ++++++++---------- 1 file changed, 77 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index bbe653714962..7ee246e07743 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -13,7 +13,7 @@ use rustc_hir::{ExprKind, HirId, Node, QPath}; use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt; use rustc_hir_analysis::check::potentially_plural_count; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; -use rustc_index::IndexVec; +use rustc_index::{Idx, IndexVec}; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::TypeError; @@ -2374,11 +2374,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let check_for_matched_generics = || { if matched_inputs.iter().any(|x| x.is_some()) - && params_with_generics.iter().any(|x| x.1.is_some()) + && params_with_generics.iter().any(|(x, _)| x.is_some()) { - for &(idx, generic, _) in ¶ms_with_generics { + for (idx, (generic, _)) in params_with_generics.iter_enumerated() { // Param has to have a generic and be matched to be relevant - if matched_inputs[idx.into()].is_none() { + if matched_inputs[idx].is_none() { continue; } @@ -2386,10 +2386,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; }; - for unmatching_idx in idx + 1..params_with_generics.len() { - if matched_inputs[unmatching_idx.into()].is_none() + for unmatching_idx in + idx.plus(1)..ExpectedIdx::from_usize(params_with_generics.len()) + { + if matched_inputs[unmatching_idx].is_none() && let Some(unmatched_idx_param_generic) = - params_with_generics[unmatching_idx].1 + params_with_generics[unmatching_idx].0 && unmatched_idx_param_generic.name.ident() == generic.name.ident() { @@ -2404,10 +2406,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let check_for_matched_generics = check_for_matched_generics(); - for &(idx, generic_param, param) in - params_with_generics.iter().filter(|&(idx, _, _)| { + for (idx, &(generic_param, param)) in + params_with_generics.iter_enumerated().filter(|&(idx, _)| { check_for_matched_generics - || expected_idx.is_none_or(|expected_idx| expected_idx == *idx) + || expected_idx + .is_none_or(|expected_idx| expected_idx == idx.as_usize()) }) { let Some(generic_param) = generic_param else { @@ -2415,29 +2418,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; }; - let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics - .iter() - .filter(|(other_idx, other_generic_param, _)| { - if *other_idx == idx { - return false; - } - let Some(other_generic_param) = other_generic_param else { - return false; - }; - if matched_inputs[idx.into()].is_none() - && matched_inputs[(*other_idx).into()].is_none() - { - return false; - } - if matched_inputs[idx.into()].is_some() - && matched_inputs[(*other_idx).into()].is_some() - { - return false; - } - other_generic_param.name.ident() == generic_param.name.ident() - }) - .map(|&(other_idx, _, other_param)| (other_idx, other_param)) - .collect(); + let other_params_matched: Vec<(ExpectedIdx, &hir::Param<'_>)> = + params_with_generics + .iter_enumerated() + .filter(|&(other_idx, &(other_generic_param, _))| { + if other_idx == idx { + return false; + } + let Some(other_generic_param) = other_generic_param else { + return false; + }; + if matched_inputs[idx].is_none() + && matched_inputs[other_idx].is_none() + { + return false; + } + if matched_inputs[idx].is_some() + && matched_inputs[other_idx].is_some() + { + return false; + } + other_generic_param.name.ident() == generic_param.name.ident() + }) + .map(|(other_idx, &(_, other_param))| (other_idx, other_param)) + .collect(); if !other_params_matched.is_empty() { let other_param_matched_names: Vec = other_params_matched @@ -2447,16 +2451,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { format!("`{ident}`") } else { - format!("parameter #{}", idx + 1) + format!("parameter #{}", idx.as_u32() + 1) } }) .collect(); let matched_ty = self - .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1) + .resolve_vars_if_possible(formal_and_expected_inputs[idx].1) .sort_string(self.tcx); - if matched_inputs[idx.into()].is_some() { + if matched_inputs[idx].is_some() { spans.push_span_label( param.span, format!( @@ -2502,19 +2506,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) { let param_idents_matching: Vec = params_with_generics - .iter() - .filter(|(_, generic, _)| { + .iter_enumerated() + .filter(|&(_, &(generic, _))| { if let Some(generic) = generic { generic.name.ident() == generic_param.name.ident() } else { false } }) - .map(|(idx, _, param)| { + .map(|(idx, &(_, param))| { if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind { format!("`{ident}`") } else { - format!("parameter #{}", idx + 1) + format!("parameter #{}", idx.as_u32() + 1) } }) .collect(); @@ -2607,12 +2611,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) { debug_assert_eq!(params_with_generics.len(), matched_inputs.len()); - for &(idx, generic_param, _) in ¶ms_with_generics { - if matched_inputs[idx.into()].is_none() { + for (idx, (generic_param, _)) in params_with_generics.iter_enumerated() { + if matched_inputs[idx].is_none() { continue; } - let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.into()) else { + let Some((_, matched_arg_span)) = provided_arg_tys.get(idx.to_provided_idx()) + else { continue; }; @@ -2620,32 +2625,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; }; - let mut idxs_matched: Vec = vec![]; - for &(other_idx, _, _) in - params_with_generics.iter().filter(|&&(other_idx, other_generic_param, _)| { + let idxs_matched = params_with_generics + .iter_enumerated() + .filter(|&(other_idx, (other_generic_param, _))| { if other_idx == idx { return false; } let Some(other_generic_param) = other_generic_param else { return false; }; - if matched_inputs[other_idx.into()].is_some() { + if matched_inputs[other_idx].is_some() { return false; } other_generic_param.name.ident() == generic_param.name.ident() }) - { - idxs_matched.push(other_idx); - } + .count(); - if idxs_matched.is_empty() { + if idxs_matched == 0 { continue; } let expected_display_type = self .resolve_vars_if_possible(formal_and_expected_inputs[idx.into()].1) .sort_string(self.tcx); - let label = if idxs_matched.len() == params_with_generics.len() - 1 { + let label = if idxs_matched == params_with_generics.len() - 1 { format!( "expected all arguments to be this {} type because they need to match the type of this parameter", expected_display_type @@ -2664,60 +2667,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Returns the parameters of a function, with their generic parameters if those are the full - /// type of that parameter. Returns `None` if the function body is unavailable (eg is an instrinsic). + /// type of that parameter. Returns `None` if the function has no generics or the body is + /// unavailable (eg is an instrinsic). fn get_hir_params_with_generics( &self, def_id: DefId, is_method: bool, - ) -> Option>, &hir::Param<'_>)>> { + ) -> Option>, &hir::Param<'_>)>> { let fn_node = self.tcx.hir().get_if_local(def_id)?; let fn_decl = fn_node.fn_decl()?; + let generic_params = fn_node.generics()?.params; - let generic_params: Vec>> = fn_decl - .inputs - .into_iter() - .skip(if is_method { 1 } else { 0 }) - .map(|param| { - if let hir::TyKind::Path(QPath::Resolved( - _, - hir::Path { res: Res::Def(_, res_def_id), .. }, - )) = param.kind - { - fn_node - .generics() - .into_iter() - .flat_map(|generics| generics.params) - .find(|param| ¶m.def_id.to_def_id() == res_def_id) - } else { - None - } - }) - .collect(); + // Remove both the receiver and variadic arguments. Neither can have an unmatched generic + // parameter. + let params = self.tcx.hir().body(fn_node.body_id()?).params; + let params = params.get(is_method as usize..params.len() - fn_decl.c_variadic as usize)?; + let fn_inputs = fn_decl.inputs.get(is_method as usize..)?; + debug_assert_eq!(params.len(), fn_inputs.len()); - let mut params: Vec<&hir::Param<'_>> = self - .tcx - .hir() - .body(fn_node.body_id()?) - .params - .into_iter() - .skip(if is_method { 1 } else { 0 }) - .collect(); - - // The surrounding code expects variadic functions to not have a parameter representing - // the "..." parameter. This is already true of the FnDecl but not of the body params, so - // we drop it if it exists. - - if fn_decl.c_variadic { - params.pop(); - } - - debug_assert_eq!(params.len(), generic_params.len()); Some( - generic_params + fn_inputs .into_iter() + .map(|param| { + if let hir::TyKind::Path(QPath::Resolved( + _, + &hir::Path { res: Res::Def(_, res_def_id), .. }, + )) = param.kind + { + generic_params.iter().find(|param| param.def_id.to_def_id() == res_def_id) + } else { + None + } + }) .zip(params) - .enumerate() - .map(|(a, (b, c))| (a, b, c)) .collect(), ) } From 6378fbc366ad552ee791bcac670e0f3939489ef7 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 3 Feb 2025 11:19:17 -0500 Subject: [PATCH 42/68] Check for generic parameter mismatches on trait functions. --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 122 ++++++++++++------ tests/ui/fn/param-mismatch-trait-fn.rs | 10 ++ tests/ui/fn/param-mismatch-trait-fn.stderr | 23 ++++ tests/ui/methods/issues/issue-61525.stderr | 2 +- ...missing-associated-type-restriction.stderr | 2 +- tests/ui/traits/issue-52893.stderr | 2 +- 6 files changed, 119 insertions(+), 42 deletions(-) create mode 100644 tests/ui/fn/param-mismatch-trait-fn.rs create mode 100644 tests/ui/fn/param-mismatch-trait-fn.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7ee246e07743..e30c0e115dc2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; -use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; @@ -2414,11 +2414,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) { let Some(generic_param) = generic_param else { - spans.push_span_label(param.span, ""); + spans.push_span_label(param.span(), ""); continue; }; - let other_params_matched: Vec<(ExpectedIdx, &hir::Param<'_>)> = + let other_params_matched: Vec<(ExpectedIdx, FnParam<'_>)> = params_with_generics .iter_enumerated() .filter(|&(other_idx, &(other_generic_param, _))| { @@ -2447,9 +2447,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let other_param_matched_names: Vec = other_params_matched .iter() .map(|(idx, other_param)| { - if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind - { - format!("`{ident}`") + if let Some(name) = other_param.name() { + format!("`{name}`") } else { format!("parameter #{}", idx.as_u32() + 1) } @@ -2462,7 +2461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if matched_inputs[idx].is_some() { spans.push_span_label( - param.span, + param.span(), format!( "{} need{} to match the {} type of this parameter", listify(&other_param_matched_names, |n| n.to_string()) @@ -2477,7 +2476,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { spans.push_span_label( - param.span, + param.span(), format!( "this parameter needs to match the {} type of {}", matched_ty, @@ -2488,7 +2487,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } generics_with_unmatched_params.push(generic_param); } else { - spans.push_span_label(param.span, ""); + spans.push_span_label(param.span(), ""); } } @@ -2515,8 +2514,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }) .map(|(idx, &(_, param))| { - if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind { - format!("`{ident}`") + if let Some(name) = param.name() { + format!("`{name}`") } else { format!("parameter #{}", idx.as_u32() + 1) } @@ -2673,35 +2672,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, def_id: DefId, is_method: bool, - ) -> Option>, &hir::Param<'_>)>> { - let fn_node = self.tcx.hir().get_if_local(def_id)?; - let fn_decl = fn_node.fn_decl()?; - let generic_params = fn_node.generics()?.params; + ) -> Option>, FnParam<'_>)>> { + let (sig, generics, body_id, param_names) = match self.tcx.hir().get_if_local(def_id)? { + hir::Node::TraitItem(&hir::TraitItem { + generics, + kind: hir::TraitItemKind::Fn(sig, trait_fn), + .. + }) => match trait_fn { + hir::TraitFn::Required(params) => (sig, generics, None, Some(params)), + hir::TraitFn::Provided(body) => (sig, generics, Some(body), None), + }, + hir::Node::ImplItem(&hir::ImplItem { + generics, + kind: hir::ImplItemKind::Fn(sig, body), + .. + }) + | hir::Node::Item(&hir::Item { + kind: hir::ItemKind::Fn { sig, generics, body, .. }, + .. + }) => (sig, generics, Some(body), None), + _ => return None, + }; - // Remove both the receiver and variadic arguments. Neither can have an unmatched generic - // parameter. - let params = self.tcx.hir().body(fn_node.body_id()?).params; - let params = params.get(is_method as usize..params.len() - fn_decl.c_variadic as usize)?; - let fn_inputs = fn_decl.inputs.get(is_method as usize..)?; - debug_assert_eq!(params.len(), fn_inputs.len()); - - Some( - fn_inputs - .into_iter() - .map(|param| { - if let hir::TyKind::Path(QPath::Resolved( - _, - &hir::Path { res: Res::Def(_, res_def_id), .. }, - )) = param.kind - { - generic_params.iter().find(|param| param.def_id.to_def_id() == res_def_id) - } else { - None - } - }) - .zip(params) - .collect(), - ) + // Make sure to remove both the receiver and variadic argument. Both are removed + // when matching parameter types. + let fn_inputs = sig.decl.inputs.get(is_method as usize..)?.iter().map(|param| { + if let hir::TyKind::Path(QPath::Resolved( + _, + &hir::Path { res: Res::Def(_, res_def_id), .. }, + )) = param.kind + { + generics.params.iter().find(|param| param.def_id.to_def_id() == res_def_id) + } else { + None + } + }); + match (body_id, param_names) { + (Some(_), Some(_)) | (None, None) => unreachable!(), + (Some(body), None) => { + let params = self.tcx.hir().body(body).params; + let params = + params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; + debug_assert_eq!(params.len(), fn_inputs.len()); + Some(fn_inputs.zip(params.iter().map(|param| FnParam::Param(param))).collect()) + } + (None, Some(params)) => { + let params = params.get(is_method as usize..)?; + debug_assert_eq!(params.len(), fn_inputs.len()); + Some(fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect()) + } + } } } @@ -2724,3 +2744,27 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { hir::intravisit::walk_expr(self, ex); } } + +#[derive(Clone, Copy)] +enum FnParam<'hir> { + Param(&'hir hir::Param<'hir>), + Name(&'hir Ident), +} +impl FnParam<'_> { + fn span(&self) -> Span { + match self { + Self::Param(x) => x.span, + Self::Name(x) => x.span, + } + } + + fn name(&self) -> Option { + match self { + Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => { + Some(ident.name) + } + Self::Name(x) if x.name != kw::Empty => Some(x.name), + _ => None, + } + } +} diff --git a/tests/ui/fn/param-mismatch-trait-fn.rs b/tests/ui/fn/param-mismatch-trait-fn.rs new file mode 100644 index 000000000000..69ded6a9068d --- /dev/null +++ b/tests/ui/fn/param-mismatch-trait-fn.rs @@ -0,0 +1,10 @@ +trait Foo { + fn same_type(_: T, _: T); +} + +fn f(x: X, y: Y) { + T::same_type([x], Some(y)); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/fn/param-mismatch-trait-fn.stderr b/tests/ui/fn/param-mismatch-trait-fn.stderr new file mode 100644 index 000000000000..28e1bcaaf49d --- /dev/null +++ b/tests/ui/fn/param-mismatch-trait-fn.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/param-mismatch-trait-fn.rs:6:23 + | +LL | T::same_type([x], Some(y)); + | ------------ --- ^^^^^^^ expected `[X; 1]`, found `Option` + | | | + | | expected all arguments to be this `[X; 1]` type because they need to match the type of this parameter + | arguments to this function are incorrect + | + = note: expected array `[X; 1]` + found enum `Option` +note: associated function defined here + --> $DIR/param-mismatch-trait-fn.rs:2:8 + | +LL | fn same_type(_: T, _: T); + | ^^^^^^^^^ - - - this parameter needs to match the `[X; 1]` type of parameter #1 + | | | + | | parameter #2 needs to match the `[X; 1]` type of this parameter + | parameter #1 and parameter #2 both reference this parameter `T` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 35001ae22a6c..7ac3d3dc0cff 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -32,7 +32,7 @@ note: method defined here --> $DIR/issue-61525.rs:2:8 | LL | fn query(self, q: Q); - | ^^^^^ + | ^^^^^ - error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr index 980c2455c8e4..df59a28c4b97 100644 --- a/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr +++ b/tests/ui/suggestions/trait-with-missing-associated-type-restriction.stderr @@ -94,7 +94,7 @@ note: method defined here --> $DIR/trait-with-missing-associated-type-restriction.rs:9:8 | LL | fn funk(&self, _: Self::A); - | ^^^^ + | ^^^^ - help: consider constraining the associated type `>::A` to `{integer}` | LL | fn bar2>(x: T) { diff --git a/tests/ui/traits/issue-52893.stderr b/tests/ui/traits/issue-52893.stderr index c37dde90e336..3c5df82fcdc8 100644 --- a/tests/ui/traits/issue-52893.stderr +++ b/tests/ui/traits/issue-52893.stderr @@ -22,7 +22,7 @@ note: method defined here --> $DIR/issue-52893.rs:11:8 | LL | fn push(self, other: T) -> Self::PushRes; - | ^^^^ + | ^^^^ ----- error: aborting due to 1 previous error From 23ab0f2cdc1f2563e258f29c37741154a2f084d6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 Jan 2025 04:23:14 +0000 Subject: [PATCH 43/68] Check Sizedness of return type in WF --- .../rustc_hir_analysis/src/check/wfcheck.rs | 30 +- compiler/rustc_hir_typeck/src/check.rs | 7 +- compiler/rustc_hir_typeck/src/lib.rs | 2 - .../traits/fulfillment_errors.rs | 5 - .../src/error_reporting/traits/overflow.rs | 1 - .../src/error_reporting/traits/suggestions.rs | 63 +-- tests/crashes/134355.rs | 6 - tests/ui/associated-consts/issue-58022.stderr | 18 +- tests/ui/consts/const-slice-array-deref.rs | 1 - .../ui/consts/const-slice-array-deref.stderr | 13 +- tests/ui/consts/const-unsized.rs | 8 +- tests/ui/consts/const-unsized.stderr | 54 +-- .../consts/const_refs_to_static-ice-121413.rs | 2 - .../const_refs_to_static-ice-121413.stderr | 11 +- tests/ui/extern-flag/empty-extern-arg.stderr | 4 + ...-trait-in-return-position-dyn-trait.stderr | 63 +-- .../dyn-trait-return-should-be-impl-trait.rs | 2 + ...n-trait-return-should-be-impl-trait.stderr | 372 ++++++++++-------- ...type-err-cause-on-impl-trait-return.stderr | 115 +++--- tests/ui/issues/issue-5883.rs | 2 +- tests/ui/issues/issue-5883.stderr | 16 +- tests/ui/lang-items/lang-item-missing.stderr | 4 + tests/ui/privacy/privacy2.rs | 4 + tests/ui/privacy/privacy2.stderr | 38 +- tests/ui/privacy/privacy3.rs | 4 + tests/ui/privacy/privacy3.stderr | 32 +- .../issue-59191-replace-root-with-fn.stderr | 6 + tests/ui/static/issue-24446.rs | 1 - tests/ui/static/issue-24446.stderr | 16 +- tests/ui/statics/unsized_type2.stderr | 14 +- ...-incompatible-trait-references-self.stderr | 24 +- .../ice-unsized-tuple-const-issue-121443.rs | 1 - ...ce-unsized-tuple-const-issue-121443.stderr | 15 +- .../const-traits/span-bug-issue-121418.stderr | 22 +- .../opaque-type-unsatisfied-bound.rs | 7 +- .../opaque-type-unsatisfied-bound.stderr | 42 +- .../opaque-type-unsatisfied-fn-bound.rs | 2 +- .../opaque-type-unsatisfied-fn-bound.stderr | 6 +- tests/ui/typeck/issue-105946.rs | 1 + tests/ui/typeck/issue-105946.stderr | 23 +- tests/ui/where-clauses/ignore-err-clauses.rs | 1 + .../where-clauses/ignore-err-clauses.stderr | 13 +- 42 files changed, 564 insertions(+), 507 deletions(-) delete mode 100644 tests/crashes/134355.rs diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 79e2d764ac59..910bcefd646f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1061,6 +1061,7 @@ fn check_associated_item( let ty = tcx.type_of(item.def_id).instantiate_identity(); let ty = wfcx.normalize(span, Some(WellFormedLoc::Ty(item_id)), ty); wfcx.register_wf_obligation(span, loc, ty.into()); + check_sized_if_body(wfcx, item.def_id.expect_local(), ty, Some(span)); Ok(()) } ty::AssocKind::Fn => { @@ -1185,7 +1186,7 @@ fn check_type_defn<'tcx>( ), wfcx.param_env, ty, - tcx.require_lang_item(LangItem::Sized, None), + tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)), ); } @@ -1312,7 +1313,7 @@ fn check_item_type( ), wfcx.param_env, item_ty, - tcx.require_lang_item(LangItem::Sized, None), + tcx.require_lang_item(LangItem::Sized, Some(ty_span)), ); } @@ -1642,6 +1643,31 @@ fn check_fn_or_method<'tcx>( ); } } + + // If the function has a body, additionally require that the return type is sized. + check_sized_if_body(wfcx, def_id, sig.output(), match hir_decl.output { + hir::FnRetTy::Return(ty) => Some(ty.span), + hir::FnRetTy::DefaultReturn(_) => None, + }); +} + +fn check_sized_if_body<'tcx>( + wfcx: &WfCheckingCtxt<'_, 'tcx>, + def_id: LocalDefId, + ty: Ty<'tcx>, + maybe_span: Option, +) { + let tcx = wfcx.tcx(); + if let Some(body) = tcx.hir().maybe_body_owned_by(def_id) { + let span = maybe_span.unwrap_or(body.value.span); + + wfcx.register_bound( + ObligationCause::new(span, def_id, traits::ObligationCauseCode::SizedReturnType), + wfcx.param_env, + ty, + tcx.require_lang_item(LangItem::Sized, Some(span)), + ); + } } /// The `arbitrary_self_types_pointers` feature implies `arbitrary_self_types`. diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index b0698183b577..97386cc77932 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -122,12 +122,7 @@ pub(super) fn check_fn<'a, 'tcx>( hir::FnRetTy::Return(ty) => ty.span, }; - fcx.require_type_is_sized( - declared_ret_ty, - return_or_body_span, - ObligationCauseCode::SizedReturnType, - ); - // We checked the root's signature during wfcheck, but not the child. + // We checked the root's ret ty during wfcheck, but not the child. if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) { fcx.require_type_is_sized( declared_ret_ty, diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 07e013e4afa6..02fbd46173c4 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -186,8 +186,6 @@ fn typeck_with_inspect<'tcx>( let wf_code = ObligationCauseCode::WellFormed(Some(WellFormedLoc::Ty(def_id))); fcx.register_wf_obligation(expected_type.into(), body.value.span, wf_code); - fcx.require_type_is_sized(expected_type, body.value.span, ObligationCauseCode::ConstSized); - // Gather locals in statics (because of block expressions). GatherLocalsVisitor::new(&fcx).visit_body(body); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 87dcdcfd6652..3128577776a8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -703,7 +703,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); err.emit() } } @@ -806,7 +805,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "Async", ); self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); return Some(err.emit()); } } @@ -852,7 +850,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "", ); self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); return Some(err.emit()); } @@ -868,7 +865,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { kind: expected_kind.as_str(), }); self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); return Some(err.emit()); } } @@ -2826,7 +2822,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_note(self.tcx.def_span(def_id), "opaque type is declared here"); self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); self.dcx().try_steal_replace_and_emit_err(self.tcx.def_span(def_id), StashKey::Cycle, err) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index fad03b5e9bf5..c5ed74420d4d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -185,7 +185,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { suggest_increasing_limit, ); self.note_obligation_cause(&mut err, &obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); err.emit() } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 24ca7bb7fc20..eb6d3ea59bb7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1781,25 +1781,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { ("dyn ", span.shrink_to_lo()) }; - let alternatively = if visitor - .returns - .iter() - .map(|expr| self.typeck_results.as_ref().unwrap().expr_ty_adjusted_opt(expr)) - .collect::>() - .len() - <= 1 - { - err.span_suggestion_verbose( - impl_span, - "consider returning an `impl Trait` instead of a `dyn Trait`", - "impl ", - Applicability::MaybeIncorrect, - ); - "alternatively, " - } else { - err.help("if there were a single returned type, you could use `impl Trait` instead"); - "" - }; + + err.span_suggestion_verbose( + impl_span, + "consider returning an `impl Trait` instead of a `dyn Trait`", + "impl ", + Applicability::MaybeIncorrect, + ); let mut sugg = vec![ (span.shrink_to_lo(), format!("Box<{pre}")), @@ -1831,7 +1819,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.multipart_suggestion( format!( - "{alternatively}box the return type, and wrap all of the returned values in \ + "alternatively, box the return type, and wrap all of the returned values in \ `Box::new`", ), sugg, @@ -1841,41 +1829,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { true } - pub(super) fn point_at_returns_when_relevant( - &self, - err: &mut Diag<'_>, - obligation: &PredicateObligation<'tcx>, - ) { - match obligation.cause.code().peel_derives() { - ObligationCauseCode::SizedReturnType => {} - _ => return, - } - - let hir = self.tcx.hir(); - let node = self.tcx.hir_node_by_def_id(obligation.cause.body_id); - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn { body: body_id, .. }, .. - }) = node - { - let body = hir.body(*body_id); - // Point at all the `return`s in the function as they have failed trait bounds. - let mut visitor = ReturnsVisitor::default(); - visitor.visit_body(body); - let typeck_results = self.typeck_results.as_ref().unwrap(); - for expr in &visitor.returns { - if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) { - let ty = self.resolve_vars_if_possible(returned_ty); - if ty.references_error() { - // don't print out the [type error] here - err.downgrade_to_delayed_bug(); - } else { - err.span_label(expr.span, format!("this returned value is of type `{ty}`")); - } - } - } - } - } - pub(super) fn report_closure_arg_mismatch( &self, span: Span, diff --git a/tests/crashes/134355.rs b/tests/crashes/134355.rs deleted file mode 100644 index b662341e6b1b..000000000000 --- a/tests/crashes/134355.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #134355 - -//@compile-flags: --crate-type=lib -fn digit() -> str { - return { i32::MIN }; -} diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr index 82cbc9ed3b09..37cb162b2b22 100644 --- a/tests/ui/associated-consts/issue-58022.stderr +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -1,12 +1,3 @@ -error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type - --> $DIR/issue-58022.rs:4:25 - | -LL | const SIZE: usize; - | ------------------ `Foo::SIZE` defined here -LL | -LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ cannot refer to the associated constant of trait - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/issue-58022.rs:13:41 | @@ -21,6 +12,15 @@ LL | pub struct Bar(T); | ^^^ = note: the return type of a function must have a statically known size +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-58022.rs:4:25 + | +LL | const SIZE: usize; + | ------------------ `Foo::SIZE` defined here +LL | +LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; + | ^^^^^^^^^ cannot refer to the associated constant of trait + error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo` --> $DIR/issue-58022.rs:15:9 | diff --git a/tests/ui/consts/const-slice-array-deref.rs b/tests/ui/consts/const-slice-array-deref.rs index 9d84ed4bdb01..99563ac968c9 100644 --- a/tests/ui/consts/const-slice-array-deref.rs +++ b/tests/ui/consts/const-slice-array-deref.rs @@ -1,6 +1,5 @@ const ONE: [u16] = [1]; //~^ ERROR the size for values of type `[u16]` cannot be known at compilation time -//~| ERROR the size for values of type `[u16]` cannot be known at compilation time //~| ERROR mismatched types const TWO: &'static u16 = &ONE[0]; diff --git a/tests/ui/consts/const-slice-array-deref.stderr b/tests/ui/consts/const-slice-array-deref.stderr index 6e69744144ed..346685380cc6 100644 --- a/tests/ui/consts/const-slice-array-deref.stderr +++ b/tests/ui/consts/const-slice-array-deref.stderr @@ -12,22 +12,13 @@ error[E0308]: mismatched types LL | const ONE: [u16] = [1]; | ^^^ expected `[u16]`, found `[u16; 1]` -error[E0277]: the size for values of type `[u16]` cannot be known at compilation time - --> $DIR/const-slice-array-deref.rs:1:20 - | -LL | const ONE: [u16] = [1]; - | ^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `[u16]` - = note: constant expressions must have a statically known size - error[E0161]: cannot move a value of type `[u16]` - --> $DIR/const-slice-array-deref.rs:6:28 + --> $DIR/const-slice-array-deref.rs:5:28 | LL | const TWO: &'static u16 = &ONE[0]; | ^^^ the size of `[u16]` cannot be statically determined -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0161, E0277, E0308. For more information about an error, try `rustc --explain E0161`. diff --git a/tests/ui/consts/const-unsized.rs b/tests/ui/consts/const-unsized.rs index 18682aa6eb61..e8af3323cebf 100644 --- a/tests/ui/consts/const-unsized.rs +++ b/tests/ui/consts/const-unsized.rs @@ -2,19 +2,19 @@ use std::fmt::Debug; const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); //~^ ERROR the size for values of type -//~| ERROR the size for values of type +//~| ERROR cannot move out of a shared reference const CONST_FOO: str = *"foo"; //~^ ERROR the size for values of type -//~| ERROR the size for values of type +//~| ERROR cannot move out of a shared reference static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); //~^ ERROR the size for values of type -//~| ERROR the size for values of type +//~| ERROR cannot move out of a shared reference static STATIC_BAR: str = *"bar"; //~^ ERROR the size for values of type -//~| ERROR the size for values of type +//~| ERROR cannot move out of a shared reference fn main() { println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR); diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr index 0b69cad96510..7931d7adafdb 100644 --- a/tests/ui/consts/const-unsized.stderr +++ b/tests/ui/consts/const-unsized.stderr @@ -6,15 +6,6 @@ LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` -error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time - --> $DIR/const-unsized.rs:3:35 - | -LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` - = note: constant expressions must have a statically known size - error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:7:18 | @@ -23,15 +14,6 @@ LL | const CONST_FOO: str = *"foo"; | = help: the trait `Sized` is not implemented for `str` -error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/const-unsized.rs:7:24 - | -LL | const CONST_FOO: str = *"foo"; - | ^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `str` - = note: constant expressions must have a statically known size - error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time --> $DIR/const-unsized.rs:11:18 | @@ -40,15 +22,6 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); | = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` -error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time - --> $DIR/const-unsized.rs:11:37 - | -LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)` - = note: constant expressions must have a statically known size - error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/const-unsized.rs:15:20 | @@ -57,14 +30,29 @@ LL | static STATIC_BAR: str = *"bar"; | = help: the trait `Sized` is not implemented for `str` -error[E0277]: the size for values of type `str` cannot be known at compilation time +error[E0507]: cannot move out of a shared reference + --> $DIR/const-unsized.rs:3:35 + | +LL | const CONST_0: dyn Debug + Sync = *(&0 as &(dyn Debug + Sync)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/const-unsized.rs:7:24 + | +LL | const CONST_FOO: str = *"foo"; + | ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference + --> $DIR/const-unsized.rs:11:37 + | +LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a shared reference --> $DIR/const-unsized.rs:15:26 | LL | static STATIC_BAR: str = *"bar"; - | ^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `str` - = note: constant expressions must have a statically known size + | ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait error[E0161]: cannot move a value of type `str` --> $DIR/const-unsized.rs:20:48 @@ -80,5 +68,5 @@ LL | println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATI error: aborting due to 10 previous errors -Some errors have detailed explanations: E0161, E0277. +Some errors have detailed explanations: E0161, E0277, E0507. For more information about an error, try `rustc --explain E0161`. diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs index 7ef67d9a9846..432ae1ad5e3b 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.rs +++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs @@ -9,11 +9,9 @@ const REF_INTERIOR_MUT: &usize = { //~^ ERROR failed to resolve: use of undeclared type `AtomicUsize` //~| WARN trait objects without an explicit `dyn` are deprecated //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| HELP if this is a dyn-compatible trait, use `dyn` //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)` - //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)` unsafe { &*(&FOO as *const _ as *const usize) } }; pub fn main() {} diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index 7beb43d84fb0..8665d9b68522 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -31,16 +31,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); | = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` -error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:8:24 - | -LL | static FOO: Sync = AtomicUsize::new(0); - | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` - = note: constant expressions must have a statically known size - -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted Some errors have detailed explanations: E0277, E0433. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 2785b12a0aef..b9a128e02e16 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -8,6 +8,10 @@ error: unwinding panics are not supported without std = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem error: requires `sized` lang_item + --> $DIR/empty-extern-arg.rs:6:11 + | +LL | fn main() {} + | ^^ error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 2869702d7fc6..3bfb0edd4c4e 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -26,42 +26,17 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `DynIncompatible` is not dyn compatible - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 - | -LL | fn cat() -> Box { - | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible - | -note: for a trait to be dyn compatible it needs to allow building a vtable - for more information, visit - --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 - | -LL | trait DynIncompatible { - | --------------- this trait is not dyn compatible... -LL | fn foo() -> Self; - | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement `DynIncompatible`: - A - B - consider defining an enum where each variant holds one of these types, - implementing `DynIncompatible` for this new enum and using it instead -help: consider turning `foo` into a method by giving it a `&self` argument - | -LL | fn foo(&self) -> Self; - | +++++ -help: alternatively, consider constraining `foo` so it does not apply to trait objects - | -LL | fn foo() -> Self where Self: Sized; - | +++++++++++++++++ - error[E0746]: return type cannot have an unboxed trait object --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | LL | fn car() -> dyn DynIncompatible { | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: if there were a single returned type, you could use `impl Trait` instead -help: box the return type, and wrap all of the returned values in `Box::new` +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn car() -> impl DynIncompatible { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | LL ~ fn car() -> Box { LL | @@ -71,6 +46,34 @@ LL | } LL ~ Box::new(B) | +error[E0038]: the trait `DynIncompatible` is not dyn compatible + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 + | +LL | fn cat() -> Box { + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 + | +LL | trait DynIncompatible { + | --------------- this trait is not dyn compatible... +LL | fn foo() -> Self; + | ^^^ ...because associated function `foo` has no `self` parameter + = help: the following types implement `DynIncompatible`: + A + B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead +help: consider turning `foo` into a method by giving it a `&self` argument + | +LL | fn foo(&self) -> Self; + | +++++ +help: alternatively, consider constraining `foo` so it does not apply to trait objects + | +LL | fn foo() -> Self where Self: Sized; + | +++++++++++++++++ + error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16 | diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs index af368203de02..ccf0a1ad3d44 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs @@ -6,9 +6,11 @@ impl Trait for u32 {} fn fuz() -> (usize, Trait) { (42, Struct) } //~^ ERROR E0277 +//~| ERROR E0277 //~| ERROR E0308 fn bar() -> (usize, dyn Trait) { (42, Struct) } //~^ ERROR E0277 +//~| ERROR E0277 //~| ERROR E0308 fn bap() -> Trait { Struct } //~^ ERROR E0746 diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 9ed3d21c13ce..86a752fb316c 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -1,49 +1,25 @@ -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35 - | -LL | fn fuz() -> (usize, Trait) { (42, Struct) } - | ^^^^^^ expected `dyn Trait`, found `Struct` - | - = note: expected trait object `(dyn Trait + 'static)` - found struct `Struct` - = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well - error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13 | LL | fn fuz() -> (usize, Trait) { (42, Struct) } - | ^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))` - | | - | doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39 - | -LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } - | ^^^^^^ expected `dyn Trait`, found `Struct` - | - = note: expected trait object `(dyn Trait + 'static)` - found struct `Struct` - = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well - error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:13 | LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } - | ^^^^^^^^^^^^^^^^^^ ------------ this returned value is of type `(usize, (dyn Trait + 'static))` - | | - | doesn't have a size known at compile-time + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 | LL | fn bap() -> Trait { Struct } | ^^^^^ doesn't have a size known at compile-time @@ -58,7 +34,7 @@ LL | fn bap() -> Box { Box::new(Struct) } | +++++++ + +++++++++ + error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13 | LL | fn ban() -> dyn Trait { Struct } | ^^^^^^^^^ doesn't have a size known at compile-time @@ -73,7 +49,7 @@ LL | fn ban() -> Box { Box::new(Struct) } | ++++ + +++++++++ + error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 | LL | fn bak() -> dyn Trait { unimplemented!() } | ^^^^^^^^^ doesn't have a size known at compile-time @@ -88,13 +64,16 @@ LL | fn bak() -> Box { Box::new(unimplemented!()) } | ++++ + +++++++++ + error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:21:13 | LL | fn bal() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | - = help: if there were a single returned type, you could use `impl Trait` instead -help: box the return type, and wrap all of the returned values in `Box::new` +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn bal() -> impl Trait { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | LL ~ fn bal() -> Box { LL | if true { @@ -104,13 +83,16 @@ LL ~ Box::new(42) | error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13 | LL | fn bax() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time | - = help: if there were a single returned type, you could use `impl Trait` instead -help: box the return type, and wrap all of the returned values in `Box::new` +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn bax() -> impl Trait { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` | LL ~ fn bax() -> Box { LL | if true { @@ -119,144 +101,8 @@ LL | } else { LL ~ Box::new(42) | -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16 - | -LL | fn bam() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -LL | if true { -LL | return Struct; - | ^^^^^^ expected `Box`, found `Struct` - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found struct `Struct` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | return Box::new(Struct); - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:5 - | -LL | fn bam() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -... -LL | 42 - | ^^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(42) - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:40:16 - | -LL | fn baq() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -LL | if true { -LL | return 0; - | ^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | return Box::new(0); - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:5 - | -LL | fn baq() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -... -LL | 42 - | ^^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(42) - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:46:9 - | -LL | fn baz() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -LL | if true { -LL | Struct - | ^^^^^^ expected `Box`, found `Struct` - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found struct `Struct` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(Struct) - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 - | -LL | fn baz() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -... -LL | 42 - | ^^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(42) - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:53:9 - | -LL | fn baw() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -LL | if true { -LL | 0 - | ^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(0) - | +++++++++ + - -error[E0308]: mismatched types - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 - | -LL | fn baw() -> Box { - | -------------- expected `Box<(dyn Trait + 'static)>` because of return type -... -LL | 42 - | ^^ expected `Box`, found integer - | - = note: expected struct `Box<(dyn Trait + 'static)>` - found type `{integer}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -help: store this in the heap by calling `Box::new` - | -LL | Box::new(42) - | +++++++++ + - error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:60:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:13 | LL | fn bat() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -275,7 +121,7 @@ LL ~ Box::new(42) | error[E0746]: return type cannot have an unboxed trait object - --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13 + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:68:13 | LL | fn bay() -> dyn Trait { | ^^^^^^^^^ doesn't have a size known at compile-time @@ -293,7 +139,183 @@ LL | } else { LL ~ Box::new(42) | -error: aborting due to 19 previous errors +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35 + | +LL | fn fuz() -> (usize, Trait) { (42, Struct) } + | ^^^^^^ expected `dyn Trait`, found `Struct` + | + = note: expected trait object `(dyn Trait + 'static)` + found struct `Struct` + = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:30 + | +LL | fn fuz() -> (usize, Trait) { (42, Struct) } + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: tuples must have a statically known size to be initialized + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:39 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^ expected `dyn Trait`, found `Struct` + | + = note: expected trait object `(dyn Trait + 'static)` + found struct `Struct` + = help: `Struct` implements `Trait` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:11:34 + | +LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } + | ^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` + = note: required because it appears within the type `(usize, (dyn Trait + 'static))` + = note: tuples must have a statically known size to be initialized + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:36:16 + | +LL | fn bam() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return Struct; + | ^^^^^^ expected `Box`, found `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(Struct); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:38:5 + | +LL | fn bam() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:42:16 + | +LL | fn baq() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | return 0; + | ^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | return Box::new(0); + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:44:5 + | +LL | fn baq() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:48:9 + | +LL | fn baz() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | Struct + | ^^^^^^ expected `Box`, found `Struct` + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found struct `Struct` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(Struct) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:50:9 + | +LL | fn baz() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:55:9 + | +LL | fn baw() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +LL | if true { +LL | 0 + | ^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(0) + | +++++++++ + + +error[E0308]: mismatched types + --> $DIR/dyn-trait-return-should-be-impl-trait.rs:57:9 + | +LL | fn baw() -> Box { + | -------------- expected `Box<(dyn Trait + 'static)>` because of return type +... +LL | 42 + | ^^ expected `Box`, found integer + | + = note: expected struct `Box<(dyn Trait + 'static)>` + found type `{integer}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +help: store this in the heap by calling `Box::new` + | +LL | Box::new(42) + | +++++++++ + + +error: aborting due to 21 previous errors Some errors have detailed explanations: E0277, E0308, E0746. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index 54849c112f5a..bd2f0ab90a52 100644 --- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -1,3 +1,62 @@ +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13 + | +LL | fn hat() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn hat() -> impl std::fmt::Display { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn hat() -> Box { +LL | match 13 { +LL | 0 => { +LL ~ return Box::new(0i32); +LL | } +LL | _ => { +LL ~ Box::new(1u32) + | + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13 + | +LL | fn pug() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn pug() -> impl std::fmt::Display { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn pug() -> Box { +LL | match 13 { +LL ~ 0 => Box::new(0i32), +LL ~ 1 => Box::new(1u32), +LL ~ _ => Box::new(2u32), + | + +error[E0746]: return type cannot have an unboxed trait object + --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13 + | +LL | fn man() -> dyn std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +help: consider returning an `impl Trait` instead of a `dyn Trait` + | +LL | fn man() -> impl std::fmt::Display { + | ~~~~ +help: alternatively, box the return type, and wrap all of the returned values in `Box::new` + | +LL ~ fn man() -> Box { +LL | if false { +LL ~ Box::new(0i32) +LL | } else { +LL ~ Box::new(1u32) + | + error[E0308]: mismatched types --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5 | @@ -165,62 +224,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | 1i32 | ~~~ -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13 - | -LL | fn hat() -> dyn std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | -help: consider returning an `impl Trait` instead of a `dyn Trait` - | -LL | fn hat() -> impl std::fmt::Display { - | ~~~~ -help: alternatively, box the return type, and wrap all of the returned values in `Box::new` - | -LL ~ fn hat() -> Box { -LL | match 13 { -LL | 0 => { -LL ~ return Box::new(0i32); -LL | } -LL | _ => { -LL ~ Box::new(1u32) - | - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13 - | -LL | fn pug() -> dyn std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | -help: consider returning an `impl Trait` instead of a `dyn Trait` - | -LL | fn pug() -> impl std::fmt::Display { - | ~~~~ -help: alternatively, box the return type, and wrap all of the returned values in `Box::new` - | -LL ~ fn pug() -> Box { -LL | match 13 { -LL ~ 0 => Box::new(0i32), -LL ~ 1 => Box::new(1u32), -LL ~ _ => Box::new(2u32), - | - -error[E0746]: return type cannot have an unboxed trait object - --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13 - | -LL | fn man() -> dyn std::fmt::Display { - | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - | - = help: if there were a single returned type, you could use `impl Trait` instead -help: box the return type, and wrap all of the returned values in `Box::new` - | -LL ~ fn man() -> Box { -LL | if false { -LL ~ Box::new(0i32) -LL | } else { -LL ~ Box::new(1u32) - | - error: aborting due to 12 previous errors Some errors have detailed explanations: E0308, E0746. diff --git a/tests/ui/issues/issue-5883.rs b/tests/ui/issues/issue-5883.rs index f9dd2c54d997..dd4753e0344a 100644 --- a/tests/ui/issues/issue-5883.rs +++ b/tests/ui/issues/issue-5883.rs @@ -6,7 +6,7 @@ struct Struct { fn new_struct( r: dyn A + 'static //~ ERROR the size for values of type -) -> Struct { +) -> Struct { //~ ERROR the size for values of type Struct { r: r } } diff --git a/tests/ui/issues/issue-5883.stderr b/tests/ui/issues/issue-5883.stderr index d481d0ef94eb..d7278ec32f53 100644 --- a/tests/ui/issues/issue-5883.stderr +++ b/tests/ui/issues/issue-5883.stderr @@ -1,3 +1,17 @@ +error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time + --> $DIR/issue-5883.rs:9:6 + | +LL | ) -> Struct { + | ^^^^^^ doesn't have a size known at compile-time + | + = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` +note: required because it appears within the type `Struct` + --> $DIR/issue-5883.rs:3:8 + | +LL | struct Struct { + | ^^^^^^ + = note: the return type of a function must have a statically known size + error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time --> $DIR/issue-5883.rs:8:8 | @@ -15,6 +29,6 @@ help: function arguments must have a statically known size, borrowed types alway LL | r: &dyn A + 'static | + -error: aborting due to 1 previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lang-items/lang-item-missing.stderr b/tests/ui/lang-items/lang-item-missing.stderr index 08e679a7c559..63bca95adf70 100644 --- a/tests/ui/lang-items/lang-item-missing.stderr +++ b/tests/ui/lang-items/lang-item-missing.stderr @@ -1,4 +1,8 @@ error: requires `sized` lang_item + --> $DIR/lang-item-missing.rs:11:60 + | +LL | extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + | ^^^ error: aborting due to 1 previous error diff --git a/tests/ui/privacy/privacy2.rs b/tests/ui/privacy/privacy2.rs index ab6d805544ee..c82cd4425596 100644 --- a/tests/ui/privacy/privacy2.rs +++ b/tests/ui/privacy/privacy2.rs @@ -14,16 +14,20 @@ mod bar { } pub fn foo() {} +//~^ ERROR requires `sized` lang_item fn test1() { + //~^ ERROR requires `sized` lang_item use bar::foo; //~^ ERROR unresolved import `bar::foo` [E0432] //~| no `foo` in `bar` } fn test2() { + //~^ ERROR requires `sized` lang_item use bar::glob::foo; //~^ ERROR `foo` is private } fn main() {} +//~^ ERROR requires `sized` lang_item diff --git a/tests/ui/privacy/privacy2.stderr b/tests/ui/privacy/privacy2.stderr index 46bb9823dbf8..39bab67a6600 100644 --- a/tests/ui/privacy/privacy2.stderr +++ b/tests/ui/privacy/privacy2.stderr @@ -1,11 +1,11 @@ error[E0432]: unresolved import `bar::foo` - --> $DIR/privacy2.rs:19:9 + --> $DIR/privacy2.rs:21:9 | LL | use bar::foo; | ^^^^^^^^ no `foo` in `bar` error[E0603]: function import `foo` is private - --> $DIR/privacy2.rs:25:20 + --> $DIR/privacy2.rs:28:20 | LL | use bar::glob::foo; | ^^^ private function import @@ -22,8 +22,40 @@ LL | pub fn foo() {} | ^^^^^^^^^^^^ you could import this directly error: requires `sized` lang_item + --> $DIR/privacy2.rs:16:14 + | +LL | pub fn foo() {} + | ^^ -error: aborting due to 3 previous errors +error: requires `sized` lang_item + --> $DIR/privacy2.rs:19:12 + | +LL | fn test1() { + | ____________^ +LL | | +LL | | use bar::foo; +... | +LL | | } + | |_^ + +error: requires `sized` lang_item + --> $DIR/privacy2.rs:26:12 + | +LL | fn test2() { + | ____________^ +LL | | +LL | | use bar::glob::foo; +LL | | +LL | | } + | |_^ + +error: requires `sized` lang_item + --> $DIR/privacy2.rs:32:11 + | +LL | fn main() {} + | ^^ + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`. diff --git a/tests/ui/privacy/privacy3.rs b/tests/ui/privacy/privacy3.rs index 6298a6bc8cf8..2bb3c1b3c61d 100644 --- a/tests/ui/privacy/privacy3.rs +++ b/tests/ui/privacy/privacy3.rs @@ -11,12 +11,15 @@ mod bar { mod glob { fn gpriv() {} + //~^ ERROR requires `sized` lang_item } } pub fn foo() {} +//~^ ERROR requires `sized` lang_item fn test1() { + //~^ ERROR requires `sized` lang_item use bar::gpriv; //~^ ERROR unresolved import `bar::gpriv` [E0432] //~| no `gpriv` in `bar` @@ -27,3 +30,4 @@ fn test1() { } fn main() {} +//~^ ERROR requires `sized` lang_item diff --git a/tests/ui/privacy/privacy3.stderr b/tests/ui/privacy/privacy3.stderr index df66c84751b7..06a287d35ea4 100644 --- a/tests/ui/privacy/privacy3.stderr +++ b/tests/ui/privacy/privacy3.stderr @@ -1,11 +1,39 @@ error[E0432]: unresolved import `bar::gpriv` - --> $DIR/privacy3.rs:20:9 + --> $DIR/privacy3.rs:23:9 | LL | use bar::gpriv; | ^^^^^^^^^^ no `gpriv` in `bar` error: requires `sized` lang_item + --> $DIR/privacy3.rs:18:14 + | +LL | pub fn foo() {} + | ^^ -error: aborting due to 2 previous errors +error: requires `sized` lang_item + --> $DIR/privacy3.rs:21:12 + | +LL | fn test1() { + | ____________^ +LL | | +LL | | use bar::gpriv; +... | +LL | | gpriv(); +LL | | } + | |_^ + +error: requires `sized` lang_item + --> $DIR/privacy3.rs:32:11 + | +LL | fn main() {} + | ^^ + +error: requires `sized` lang_item + --> $DIR/privacy3.rs:13:20 + | +LL | fn gpriv() {} + | ^^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr index 08e679a7c559..2d0c92ff2974 100644 --- a/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr +++ b/tests/ui/proc-macro/issue-59191-replace-root-with-fn.stderr @@ -1,4 +1,10 @@ error: requires `sized` lang_item + --> $DIR/issue-59191-replace-root-with-fn.rs:9:1 + | +LL | #![issue_59191::no_main] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/static/issue-24446.rs b/tests/ui/static/issue-24446.rs index 6cf8846506d3..830e373c189d 100644 --- a/tests/ui/static/issue-24446.rs +++ b/tests/ui/static/issue-24446.rs @@ -2,7 +2,6 @@ fn main() { static foo: dyn Fn() -> u32 = || -> u32 { //~^ ERROR the size for values of type //~| ERROR cannot be shared between threads safely - //~| ERROR the size for values of type //~| ERROR mismatched types 0 }; diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr index 8cb034000bed..033caf07d8e5 100644 --- a/tests/ui/static/issue-24446.stderr +++ b/tests/ui/static/issue-24446.stderr @@ -15,33 +15,19 @@ LL | static foo: dyn Fn() -> u32 = || -> u32 { | = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` -error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time - --> $DIR/issue-24446.rs:2:35 - | -LL | static foo: dyn Fn() -> u32 = || -> u32 { - | ___________________________________^ -... | -LL | | 0 -LL | | }; - | |_____^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)` - = note: constant expressions must have a statically known size - error[E0308]: mismatched types --> $DIR/issue-24446.rs:2:35 | LL | static foo: dyn Fn() -> u32 = || -> u32 { | ___________________________________^ ... | -LL | | 0 LL | | }; | |_____^ expected `dyn Fn`, found closure | = note: expected trait object `(dyn Fn() -> u32 + 'static)` found closure `{closure@$DIR/issue-24446.rs:2:35: 2:44}` -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr index b18a99fab72c..ffbbe218c87a 100644 --- a/tests/ui/statics/unsized_type2.stderr +++ b/tests/ui/statics/unsized_type2.stderr @@ -11,6 +11,12 @@ note: required because it appears within the type `Foo` LL | pub struct Foo { | ^^^ +error[E0308]: mismatched types + --> $DIR/unsized_type2.rs:14:45 + | +LL | pub static WITH_ERROR: Foo = Foo { version: 0 }; + | ^ expected `str`, found integer + error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/unsized_type2.rs:14:30 | @@ -23,13 +29,7 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ - = note: constant expressions must have a statically known size - -error[E0308]: mismatched types - --> $DIR/unsized_type2.rs:14:45 - | -LL | pub static WITH_ERROR: Foo = Foo { version: 0 }; - | ^ expected `str`, found integer + = note: structs must have a statically known size to be initialized error: aborting due to 3 previous errors diff --git a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr index ae009d260299..4576017abaf4 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr @@ -33,6 +33,18 @@ LL | trait Other: Sized {} | | | this trait is not dyn compatible... +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/dyn-incompatible-trait-references-self.rs:4:22 + | +LL | fn bat(&self) -> Self {} + | ^^^^ doesn't have a size known at compile-time + | + = note: the return type of a function must have a statically known size +help: consider further restricting `Self` + | +LL | fn bat(&self) -> Self where Self: Sized {} + | +++++++++++++++++ + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | @@ -61,18 +73,6 @@ LL | fn bat(&self) -> Self {} = note: expected type parameter `Self` found unit type `()` -error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/dyn-incompatible-trait-references-self.rs:4:22 - | -LL | fn bat(&self) -> Self {} - | ^^^^ doesn't have a size known at compile-time - | - = note: the return type of a function must have a statically known size -help: consider further restricting `Self` - | -LL | fn bat(&self) -> Self where Self: Sized {} - | +++++++++++++++++ - error: aborting due to 5 previous errors Some errors have detailed explanations: E0038, E0277, E0308. diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs index c3a2ab82adc6..5277de29464d 100644 --- a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.rs @@ -8,7 +8,6 @@ type Fn = dyn FnOnce() -> u8; const TEST: Fn = some_fn; //~^ ERROR cannot find value `some_fn` in this scope //~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time -//~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time const TEST2: (Fn, u8) = (TEST, 0); //~^ ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time //~| ERROR the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time diff --git a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr index 0e92979ccd50..76e015a7238b 100644 --- a/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr +++ b/tests/ui/trait-bounds/ice-unsized-tuple-const-issue-121443.stderr @@ -13,16 +13,7 @@ LL | const TEST: Fn = some_fn; = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time - --> $DIR/ice-unsized-tuple-const-issue-121443.rs:8:18 - | -LL | const TEST: Fn = some_fn; - | ^^^^^^^ doesn't have a size known at compile-time - | - = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` - = note: constant expressions must have a statically known size - -error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time - --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:14 + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:11:14 | LL | const TEST2: (Fn, u8) = (TEST, 0); | ^^^^^^^^ doesn't have a size known at compile-time @@ -31,7 +22,7 @@ LL | const TEST2: (Fn, u8) = (TEST, 0); = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `(dyn FnOnce() -> u8 + 'static)` cannot be known at compilation time - --> $DIR/ice-unsized-tuple-const-issue-121443.rs:12:25 + --> $DIR/ice-unsized-tuple-const-issue-121443.rs:11:25 | LL | const TEST2: (Fn, u8) = (TEST, 0); | ^^^^^^^^^ doesn't have a size known at compile-time @@ -39,7 +30,7 @@ LL | const TEST2: (Fn, u8) = (TEST, 0); = help: the trait `Sized` is not implemented for `(dyn FnOnce() -> u8 + 'static)` = note: only the last element of a tuple may have a dynamically sized type -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0425. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr index f41c19b45739..92cfecd05404 100644 --- a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr +++ b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr @@ -8,17 +8,6 @@ LL | impl const dyn T { | = note: only trait implementations may be annotated with `const` -error[E0308]: mismatched types - --> $DIR/span-bug-issue-121418.rs:8:27 - | -LL | pub const fn new() -> std::sync::Mutex {} - | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex`, found `()` - | | - | implicitly returns `()` as its body has no tail or `return` expression - | - = note: expected struct `Mutex<(dyn T + 'static)>` - found unit type `()` - error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time --> $DIR/span-bug-issue-121418.rs:8:27 | @@ -30,6 +19,17 @@ note: required because it appears within the type `Mutex<(dyn T + 'static)>` --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL = note: the return type of a function must have a statically known size +error[E0308]: mismatched types + --> $DIR/span-bug-issue-121418.rs:8:27 + | +LL | pub const fn new() -> std::sync::Mutex {} + | --- ^^^^^^^^^^^^^^^^^^^^^^^ expected `Mutex`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected struct `Mutex<(dyn T + 'static)>` + found unit type `()` + error: aborting due to 3 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs index cbd591eec96c..ea6df9387047 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs @@ -13,8 +13,9 @@ fn main() { } fn weird0() -> impl Sized + !Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving fn weird1() -> impl !Sized + Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving fn weird2() -> impl !Sized {} -//~^ ERROR the trait bound `(): !Sized` is not satisfied +//~^ ERROR type mismatch resolving +//~| ERROR the size for values of type diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr index 3dad6d534fd8..41d9e74f8076 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr @@ -1,20 +1,29 @@ -error[E0277]: the trait bound `(): !Sized` is not satisfied - --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 - | -LL | fn weird0() -> impl Sized + !Sized {} - | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied - -error[E0277]: the trait bound `(): !Sized` is not satisfied - --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 - | -LL | fn weird1() -> impl !Sized + Sized {} - | ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied - -error[E0277]: the trait bound `(): !Sized` is not satisfied +error[E0277]: the size for values of type `impl !Sized` cannot be known at compilation time --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 | LL | fn weird2() -> impl !Sized {} - | ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied + | ^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `impl !Sized` + = note: the return type of a function must have a statically known size + +error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` + --> $DIR/opaque-type-unsatisfied-bound.rs:15:16 + | +LL | fn weird0() -> impl Sized + !Sized {} + | ^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `impl !Sized + Sized == ()` + --> $DIR/opaque-type-unsatisfied-bound.rs:17:16 + | +LL | fn weird1() -> impl !Sized + Sized {} + | ^^^^^^^^^^^^^^^^^^^ types differ + +error[E0271]: type mismatch resolving `impl !Sized == ()` + --> $DIR/opaque-type-unsatisfied-bound.rs:19:16 + | +LL | fn weird2() -> impl !Sized {} + | ^^^^^^^^^^^ types differ error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied --> $DIR/opaque-type-unsatisfied-bound.rs:12:13 @@ -30,6 +39,7 @@ note: required by a bound in `consume` LL | fn consume(_: impl Trait) {} | ^^^^^ required by this bound in `consume` -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs index 39422914afcd..ce42bce0ad4e 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs @@ -3,6 +3,6 @@ #![feature(negative_bounds, unboxed_closures)] fn produce() -> impl !Fn<(u32,)> {} -//~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied +//~^ ERROR type mismatch resolving fn main() {} diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr index 760e5aa62f2c..e1b84e0df7a5 100644 --- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr +++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr @@ -1,9 +1,9 @@ -error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied +error[E0271]: type mismatch resolving `impl !Fn<(u32,)> == ()` --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17 | LL | fn produce() -> impl !Fn<(u32,)> {} - | ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied + | ^^^^^^^^^^^^^^^^ types differ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/typeck/issue-105946.rs b/tests/ui/typeck/issue-105946.rs index f53f31138f81..0ee70f9346c8 100644 --- a/tests/ui/typeck/issue-105946.rs +++ b/tests/ui/typeck/issue-105946.rs @@ -1,4 +1,5 @@ fn digit() -> str { + //~^ ERROR the size for values of type return {}; //~^ ERROR: mismatched types [E0308] } diff --git a/tests/ui/typeck/issue-105946.stderr b/tests/ui/typeck/issue-105946.stderr index 33d4e0b141ab..30fe2000a461 100644 --- a/tests/ui/typeck/issue-105946.stderr +++ b/tests/ui/typeck/issue-105946.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find value `_y` in this scope - --> $DIR/issue-105946.rs:6:10 + --> $DIR/issue-105946.rs:7:10 | LL | let [_y..] = [Box::new(1), Box::new(2)]; | ^^ not found in this scope @@ -10,7 +10,7 @@ LL | let [_y @ ..] = [Box::new(1), Box::new(2)]; | + error[E0658]: `X..` patterns in slices are experimental - --> $DIR/issue-105946.rs:6:10 + --> $DIR/issue-105946.rs:7:10 | LL | let [_y..] = [Box::new(1), Box::new(2)]; | ^^^^ @@ -19,19 +19,28 @@ LL | let [_y..] = [Box::new(1), Box::new(2)]; = help: add `#![feature(half_open_range_patterns_in_slices)]` 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[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/issue-105946.rs:1:15 + | +LL | fn digit() -> str { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + error[E0308]: mismatched types - --> $DIR/issue-105946.rs:2:12 + --> $DIR/issue-105946.rs:3:12 | LL | return {}; | ^^ expected `str`, found `()` error[E0527]: pattern requires 1 element but array has 2 - --> $DIR/issue-105946.rs:6:9 + --> $DIR/issue-105946.rs:7:9 | LL | let [_y..] = [Box::new(1), Box::new(2)]; | ^^^^^^ expected 2 elements -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0425, E0527, E0658. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308, E0425, E0527, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/ignore-err-clauses.rs b/tests/ui/where-clauses/ignore-err-clauses.rs index c76f0e1a8b2b..428ebf4b4083 100644 --- a/tests/ui/where-clauses/ignore-err-clauses.rs +++ b/tests/ui/where-clauses/ignore-err-clauses.rs @@ -1,6 +1,7 @@ use std::ops::Add; fn dbl(x: T) -> ::Output +//~^ ERROR type annotations needed where T: Copy + Add, UUU: Copy, diff --git a/tests/ui/where-clauses/ignore-err-clauses.stderr b/tests/ui/where-clauses/ignore-err-clauses.stderr index 4cf553da4c5f..fbf1b99334f4 100644 --- a/tests/ui/where-clauses/ignore-err-clauses.stderr +++ b/tests/ui/where-clauses/ignore-err-clauses.stderr @@ -1,9 +1,16 @@ error[E0412]: cannot find type `UUU` in this scope - --> $DIR/ignore-err-clauses.rs:6:5 + --> $DIR/ignore-err-clauses.rs:7:5 | LL | UUU: Copy, | ^^^ not found in this scope -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/ignore-err-clauses.rs:3:14 + | +LL | fn dbl(x: T) -> ::Output + | ^ cannot infer type for type parameter `T` -For more information about this error, try `rustc --explain E0412`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0412. +For more information about an error, try `rustc --explain E0282`. From 0d907c17a8258b012f6b1e327709ef5789128167 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Feb 2025 14:58:12 +0000 Subject: [PATCH 44/68] Make error message less awkward --- compiler/rustc_hir_typeck/src/check.rs | 12 ++++++------ .../src/error_reporting/traits/suggestions.rs | 2 +- tests/ui/error-codes/E0746.stderr | 4 ++-- ...ompatible-trait-in-return-position-dyn-trait.rs | 2 +- ...tible-trait-in-return-position-dyn-trait.stderr | 2 +- .../dyn-trait-return-should-be-impl-trait.stderr | 14 +++++++------- ...point-to-type-err-cause-on-impl-trait-return.rs | 6 +++--- ...t-to-type-err-cause-on-impl-trait-return.stderr | 6 +++--- tests/ui/issues/issue-18107.rs | 2 +- tests/ui/issues/issue-18107.stderr | 2 +- tests/ui/unsized/box-instead-of-dyn-fn.rs | 2 +- tests/ui/unsized/box-instead-of-dyn-fn.stderr | 2 +- tests/ui/unsized/issue-91801.rs | 2 +- tests/ui/unsized/issue-91801.stderr | 2 +- tests/ui/unsized/issue-91803.rs | 2 +- tests/ui/unsized/issue-91803.stderr | 2 +- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 97386cc77932..9fdc5a0ae4e1 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -117,17 +117,17 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - let return_or_body_span = match decl.output { - hir::FnRetTy::DefaultReturn(_) => body.value.span, - hir::FnRetTy::Return(ty) => ty.span, - }; - // We checked the root's ret ty during wfcheck, but not the child. if fcx.tcx.is_typeck_child(fn_def_id.to_def_id()) { + let return_or_body_span = match decl.output { + hir::FnRetTy::DefaultReturn(_) => body.value.span, + hir::FnRetTy::Return(ty) => ty.span, + }; + fcx.require_type_is_sized( declared_ret_ty, return_or_body_span, - ObligationCauseCode::WellFormed(None), + ObligationCauseCode::SizedReturnType, ); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index eb6d3ea59bb7..c194cc11727d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; err.code(E0746); - err.primary_message("return type cannot have an unboxed trait object"); + err.primary_message("return type cannot be a trait object without pointer indirection"); err.children.clear(); let span = obligation.cause.span; diff --git a/tests/ui/error-codes/E0746.stderr b/tests/ui/error-codes/E0746.stderr index ce3e97369694..ec785561415a 100644 --- a/tests/ui/error-codes/E0746.stderr +++ b/tests/ui/error-codes/E0746.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/E0746.rs:8:13 | LL | fn foo() -> dyn Trait { Struct } @@ -13,7 +13,7 @@ help: alternatively, box the return type, and wrap all of the returned values in LL | fn foo() -> Box { Box::new(Struct) } | ++++ + +++++++++ + -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/E0746.rs:11:13 | LL | fn bar() -> dyn Trait { diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index 046ced072bac..901d4b39cf36 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -20,7 +20,7 @@ impl DynIncompatible for B { } fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not dyn compatible -//~^ ERROR return type cannot have an unboxed trait object +//~^ ERROR return type cannot be a trait object without pointer indirection if true { return A; } diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 3bfb0edd4c4e..c2fd11fe23de 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -26,7 +26,7 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | LL | fn car() -> dyn DynIncompatible { diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr index 86a752fb316c..11491a55738b 100644 --- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr +++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr @@ -18,7 +18,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) } = note: required because it appears within the type `(usize, (dyn Trait + 'static))` = note: the return type of a function must have a statically known size -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13 | LL | fn bap() -> Trait { Struct } @@ -33,7 +33,7 @@ help: alternatively, box the return type, and wrap all of the returned values in LL | fn bap() -> Box { Box::new(Struct) } | +++++++ + +++++++++ + -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13 | LL | fn ban() -> dyn Trait { Struct } @@ -48,7 +48,7 @@ help: alternatively, box the return type, and wrap all of the returned values in LL | fn ban() -> Box { Box::new(Struct) } | ++++ + +++++++++ + -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13 | LL | fn bak() -> dyn Trait { unimplemented!() } @@ -63,7 +63,7 @@ help: alternatively, box the return type, and wrap all of the returned values in LL | fn bak() -> Box { Box::new(unimplemented!()) } | ++++ + +++++++++ + -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:21:13 | LL | fn bal() -> dyn Trait { @@ -82,7 +82,7 @@ LL | } LL ~ Box::new(42) | -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13 | LL | fn bax() -> dyn Trait { @@ -101,7 +101,7 @@ LL | } else { LL ~ Box::new(42) | -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:62:13 | LL | fn bat() -> dyn Trait { @@ -120,7 +120,7 @@ LL | } LL ~ Box::new(42) | -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/dyn-trait-return-should-be-impl-trait.rs:68:13 | LL | fn bay() -> dyn Trait { diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs index a8a6288eb56f..719edd525dea 100644 --- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs +++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs @@ -63,7 +63,7 @@ fn dog() -> impl std::fmt::Display { } } -fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object +fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot be a trait object without pointer indirection match 13 { 0 => { return 0i32; @@ -74,7 +74,7 @@ fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed } } -fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object +fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot be a trait object without pointer indirection match 13 { 0 => 0i32, 1 => 1u32, @@ -82,7 +82,7 @@ fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed } } -fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object +fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot be a trait object without pointer indirection if false { 0i32 } else { diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr index bd2f0ab90a52..17eaed436dfb 100644 --- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr +++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13 | LL | fn hat() -> dyn std::fmt::Display { @@ -19,7 +19,7 @@ LL | _ => { LL ~ Box::new(1u32) | -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13 | LL | fn pug() -> dyn std::fmt::Display { @@ -38,7 +38,7 @@ LL ~ 1 => Box::new(1u32), LL ~ _ => Box::new(2u32), | -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13 | LL | fn man() -> dyn std::fmt::Display { diff --git a/tests/ui/issues/issue-18107.rs b/tests/ui/issues/issue-18107.rs index 4bf5b6c0f303..b1b6ff4f7ad2 100644 --- a/tests/ui/issues/issue-18107.rs +++ b/tests/ui/issues/issue-18107.rs @@ -2,7 +2,7 @@ pub trait AbstractRenderer {} fn _create_render(_: &()) -> dyn AbstractRenderer -//~^ ERROR return type cannot have an unboxed trait object +//~^ ERROR return type cannot be a trait object without pointer indirection { match 0 { _ => unimplemented!() diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr index 705f7d0df12a..6956d6a34aa2 100644 --- a/tests/ui/issues/issue-18107.stderr +++ b/tests/ui/issues/issue-18107.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/issue-18107.rs:4:5 | LL | dyn AbstractRenderer diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.rs b/tests/ui/unsized/box-instead-of-dyn-fn.rs index 321c2ebf5a12..720176081d6f 100644 --- a/tests/ui/unsized/box-instead-of-dyn-fn.rs +++ b/tests/ui/unsized/box-instead-of-dyn-fn.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; // Test to suggest boxing the return type, and the closure branch of the `if` fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { - //~^ ERROR return type cannot have an unboxed trait object + //~^ ERROR return type cannot be a trait object without pointer indirection if a % 2 == 0 { move || println!("{a}") } else { diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr index 1f1845569ef1..1836d5dfffe2 100644 --- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr +++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/box-instead-of-dyn-fn.rs:5:56 | LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a { diff --git a/tests/ui/unsized/issue-91801.rs b/tests/ui/unsized/issue-91801.rs index 096b1a93574f..d906a08a55a2 100644 --- a/tests/ui/unsized/issue-91801.rs +++ b/tests/ui/unsized/issue-91801.rs @@ -6,7 +6,7 @@ pub static ALL_VALIDATORS: &[(&'static str, &'static Validator)] = &[("validate that credits and debits balance", &validate_something)]; fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { - //~^ ERROR return type cannot have an unboxed trait object + //~^ ERROR return type cannot be a trait object without pointer indirection return Box::new(move |something: &'_ Something| -> Result<(), ()> { first(something).or_else(|_| second(something)) }); diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr index e13cabbb81d6..28e10f9caa41 100644 --- a/tests/ui/unsized/issue-91801.stderr +++ b/tests/ui/unsized/issue-91801.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/issue-91801.rs:8:77 | LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> { diff --git a/tests/ui/unsized/issue-91803.rs b/tests/ui/unsized/issue-91803.rs index c74897cc4bc5..8d35c7582b82 100644 --- a/tests/ui/unsized/issue-91803.rs +++ b/tests/ui/unsized/issue-91803.rs @@ -1,7 +1,7 @@ trait Foo<'a> {} fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { - //~^ ERROR return type cannot have an unboxed trait object + //~^ ERROR return type cannot be a trait object without pointer indirection return Box::new(panic!()); } diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr index 3b89066499df..e0fde4b1c1bc 100644 --- a/tests/ui/unsized/issue-91803.stderr +++ b/tests/ui/unsized/issue-91803.stderr @@ -1,4 +1,4 @@ -error[E0746]: return type cannot have an unboxed trait object +error[E0746]: return type cannot be a trait object without pointer indirection --> $DIR/issue-91803.rs:3:43 | LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> { From bda6742797ada7b095697eb7d8671e2a7ac10731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Feb 2025 19:02:26 +0000 Subject: [PATCH 45/68] fix `crateresolve*.rs` tests and duplicates for compare modes - duplicates of crateresolve1 are used in a couple error-codes tests - also fix the note in crateresolve1 to link to these other duplicates, now that E0523 has been merged into E0464 --- tests/ui/crate-loading/crateresolve1.rs | 4 ++-- tests/ui/crate-loading/crateresolve2.rs | 2 +- tests/ui/error-codes/E0464.rs | 2 +- tests/ui/error-codes/E0523.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/ui/crate-loading/crateresolve1.rs b/tests/ui/crate-loading/crateresolve1.rs index 9200b6a62314..91c34c82558e 100644 --- a/tests/ui/crate-loading/crateresolve1.rs +++ b/tests/ui/crate-loading/crateresolve1.rs @@ -2,11 +2,11 @@ //@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-3.rs -//@ normalize-stderr: "\.nll/" -> "/" +//@ normalize-stderr: "crateresolve1\..+/auxiliary/" -> "crateresolve1/auxiliary/" //@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" -// NOTE: This test is duplicated at `tests/ui/error-codes/E0464.rs`. +// NOTE: This test is duplicated at `tests/ui/error-codes/E0464.rs` and `E0523.rs`. extern crate crateresolve1; //~^ ERROR multiple candidates for `rlib` dependency `crateresolve1` found diff --git a/tests/ui/crate-loading/crateresolve2.rs b/tests/ui/crate-loading/crateresolve2.rs index bec692eb8d2b..6446740a3210 100644 --- a/tests/ui/crate-loading/crateresolve2.rs +++ b/tests/ui/crate-loading/crateresolve2.rs @@ -4,7 +4,7 @@ //@ aux-build:crateresolve2-2.rs //@ aux-build:crateresolve2-3.rs -//@ normalize-stderr: "\.nll/" -> "/" +//@ normalize-stderr: "crateresolve2\..+/auxiliary/" -> "crateresolve2/auxiliary/" //@ normalize-stderr: "\\\?\\" -> "" extern crate crateresolve2; diff --git a/tests/ui/error-codes/E0464.rs b/tests/ui/error-codes/E0464.rs index aaf4d3a8f500..d1303ae91b1d 100644 --- a/tests/ui/error-codes/E0464.rs +++ b/tests/ui/error-codes/E0464.rs @@ -2,7 +2,7 @@ //@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-3.rs -//@ normalize-stderr: "\.nll/" -> "/" +//@ normalize-stderr: "E0464\..+/auxiliary/" -> "E0464/auxiliary/" //@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" diff --git a/tests/ui/error-codes/E0523.rs b/tests/ui/error-codes/E0523.rs index aaf4d3a8f500..7c1869c055b2 100644 --- a/tests/ui/error-codes/E0523.rs +++ b/tests/ui/error-codes/E0523.rs @@ -2,7 +2,7 @@ //@ aux-build:crateresolve1-2.rs //@ aux-build:crateresolve1-3.rs -//@ normalize-stderr: "\.nll/" -> "/" +//@ normalize-stderr: "E0523\..+/auxiliary/" -> "E0523/auxiliary/" //@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "(lib)?crateresolve1-([123])\.[a-z]+" -> "libcrateresolve1-$2.somelib" From 6825f176d657df5d73287c71421aef10c5b23e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Feb 2025 19:08:21 +0000 Subject: [PATCH 46/68] fix normalization in `E0271` test for compare-modes --- tests/ui/diagnostic-width/E0271.ascii.stderr | 2 +- tests/ui/diagnostic-width/E0271.rs | 2 +- tests/ui/diagnostic-width/E0271.unicode.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/diagnostic-width/E0271.ascii.stderr b/tests/ui/diagnostic-width/E0271.ascii.stderr index 93555b336a66..9a9c12a938f6 100644 --- a/tests/ui/diagnostic-width/E0271.ascii.stderr +++ b/tests/ui/diagnostic-width/E0271.ascii.stderr @@ -15,7 +15,7 @@ note: expected this to be `Foo` LL | type Error = E; | ^ = note: required for the cast from `Box>` to `Box<...>` - = note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.ascii/E0271.long-type-hash.txt' + = note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' = note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic-width/E0271.rs b/tests/ui/diagnostic-width/E0271.rs index 2faf09d46c6e..061877210414 100644 --- a/tests/ui/diagnostic-width/E0271.rs +++ b/tests/ui/diagnostic-width/E0271.rs @@ -1,7 +1,7 @@ //@ revisions: ascii unicode //@[ascii] compile-flags: --diagnostic-width=40 -Zwrite-long-types-to-disk=yes //@[unicode] compile-flags: -Zunstable-options --error-format=human-unicode --diagnostic-width=40 -Zwrite-long-types-to-disk=yes -//@ normalize-stderr: "long-type-\d+" -> "long-type-hash" +//@ normalize-stderr: "'\$TEST_BUILD_DIR/.*\.long-type-\d+.txt'" -> "'$$TEST_BUILD_DIR/$$FILE.long-type-hash.txt'" trait Future { type Error; } diff --git a/tests/ui/diagnostic-width/E0271.unicode.stderr b/tests/ui/diagnostic-width/E0271.unicode.stderr index 1e9acf603b2b..9c3deae66608 100644 --- a/tests/ui/diagnostic-width/E0271.unicode.stderr +++ b/tests/ui/diagnostic-width/E0271.unicode.stderr @@ -15,7 +15,7 @@ note: expected this to be `Foo` LL │ type Error = E; │ ━ ├ note: required for the cast from `Box>` to `Box<...>` - ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/diagnostic-width/E0271.unicode/E0271.long-type-hash.txt' + ├ note: the full name for the type has been written to '$TEST_BUILD_DIR/$FILE.long-type-hash.txt' ╰ note: consider using `--verbose` to print the full type name to the console error: aborting due to 1 previous error From 62d0771ad43cd0b04e0d790dd64e35f702d4637a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Feb 2025 19:15:37 +0000 Subject: [PATCH 47/68] fix `json-*.rs` and `E0462` tests for compare-modes --- tests/ui/error-codes/E0462.rs | 2 +- tests/ui/json/json-multiple.rs | 1 + tests/ui/json/json-options.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ui/error-codes/E0462.rs b/tests/ui/error-codes/E0462.rs index 12214331445f..45d35c345cb5 100644 --- a/tests/ui/error-codes/E0462.rs +++ b/tests/ui/error-codes/E0462.rs @@ -1,6 +1,6 @@ //@ aux-build:found-staticlib.rs -//@ normalize-stderr: "\.nll/" -> "/" +//@ normalize-stderr: "E0462\..+/auxiliary/" -> "E0462/auxiliary/" //@ normalize-stderr: "\\\?\\" -> "" //@ normalize-stderr: "(lib)?found_staticlib\.[a-z]+" -> "libfound_staticlib.somelib" diff --git a/tests/ui/json/json-multiple.rs b/tests/ui/json/json-multiple.rs index 296a60d24537..8ad57939d5d1 100644 --- a/tests/ui/json/json-multiple.rs +++ b/tests/ui/json/json-multiple.rs @@ -1,5 +1,6 @@ //@ build-pass //@ ignore-pass (different metadata emitted in different modes) //@ compile-flags: --json=diagnostic-short --json artifacts --error-format=json +//@ normalize-stderr: "json-multiple\..+/libjson_multiple.rlib" -> "json-multiple/libjson_multiple.rlib" #![crate_type = "lib"] diff --git a/tests/ui/json/json-options.rs b/tests/ui/json/json-options.rs index 33df25e27b6a..a6654bfcac6f 100644 --- a/tests/ui/json/json-options.rs +++ b/tests/ui/json/json-options.rs @@ -1,5 +1,6 @@ //@ build-pass //@ ignore-pass (different metadata emitted in different modes) //@ compile-flags: --json=diagnostic-short,artifacts --error-format=json +//@ normalize-stderr: "json-options\..+/libjson_options.rlib" -> "json-options/libjson_options.rlib" #![crate_type = "lib"] From f4a92e3262dbf98304758c5f778ddd6528b47f44 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 3 Feb 2025 16:55:34 +0100 Subject: [PATCH 48/68] Add `cast_signed` and `cast_unsigned` methods for `NonZero` types --- library/core/src/num/nonzero.rs | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 3becbc9bade3..a115acf42b12 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1626,6 +1626,29 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // results will be sqrt(1), which is 1, so a result can't be zero. unsafe { Self::new_unchecked(result) } } + + /// Returns the bit pattern of `self` reinterpreted as a signed integer of the same size. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// # use std::num::NonZero; + /// + #[doc = concat!("let n = NonZero::<", stringify!($Int), ">::MAX;")] + /// + #[doc = concat!("assert_eq!(n.cast_signed(), NonZero::new(-1", stringify!($Sint), ").unwrap());")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_signed(self) -> NonZero<$Sint> { + // SAFETY: `self.get()` can't be zero + unsafe { NonZero::new_unchecked(self.get().cast_signed()) } + } }; // Associated items for signed nonzero types only. @@ -2042,6 +2065,30 @@ macro_rules! nonzero_integer_signedness_dependent_methods { // SAFETY: negation of nonzero cannot yield zero values. unsafe { Self::new_unchecked(result) } } + + /// Returns the bit pattern of `self` reinterpreted as an unsigned integer of the same size. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(integer_sign_cast)] + /// # use std::num::NonZero; + /// + #[doc = concat!("let n = NonZero::new(-1", stringify!($Int), ").unwrap();")] + /// + #[doc = concat!("assert_eq!(n.cast_unsigned(), NonZero::<", stringify!($Uint), ">::MAX);")] + /// ``` + #[unstable(feature = "integer_sign_cast", issue = "125882")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn cast_unsigned(self) -> NonZero<$Uint> { + // SAFETY: `self.get()` can't be zero + unsafe { NonZero::new_unchecked(self.get().cast_unsigned()) } + } + }; } From 0825202cf296d319e9bbfdbf445723f92d618fc0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 10:20:33 +1100 Subject: [PATCH 49/68] Remove unused features from `rustc_middle`. --- compiler/rustc_middle/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index bbe23d8abe8a..9d2aae1477b5 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -37,7 +37,6 @@ #![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] -#![feature(const_type_name)] #![feature(core_intrinsics)] #![feature(coroutines)] #![feature(debug_closure_helpers)] @@ -50,7 +49,6 @@ #![feature(intra_doc_pointers)] #![feature(iter_from_coroutine)] #![feature(let_chains)] -#![feature(macro_metavar_expr)] #![feature(min_specialization)] #![feature(negative_impls)] #![feature(never_type)] From 1fa9200475dae485dadf90845249f58395a33168 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 19:23:34 +1100 Subject: [PATCH 50/68] Remove `dep_node` comment duplication. `rustc_middle` and `rustc_query_system` both have a file called `dep_node.rs` with a big comment at the top, and the comments are very similar. The one in `rustc_query_system` looks like the original, and the one in `rustc_middle` is a copy with some improvements. This commit removes the comment from `rustc_middle` and updates the one in `rustc_query_system` to include the improvements. I did it this way because `rustc_query_system` is the crate that defines `DepNode`, and so seems like the right place for the comment. --- .../rustc_middle/src/dep_graph/dep_node.rs | 58 ------------------- .../src/dep_graph/dep_node.rs | 39 ++++++++----- 2 files changed, 26 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index fcfc31575f8a..9afba83a4f8d 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -1,61 +1,3 @@ -//! Nodes in the dependency graph. -//! -//! A node in the [dependency graph] is represented by a [`DepNode`]. -//! A `DepNode` consists of a [`DepKind`] (which -//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.) -//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which -//! depends on the node's `DepKind`. Together, the kind and the fingerprint -//! fully identify a dependency node, even across multiple compilation sessions. -//! In other words, the value of the fingerprint does not depend on anything -//! that is specific to a given compilation session, like an unpredictable -//! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a -//! pointer. The concept behind this could be compared to how git commit hashes -//! uniquely identify a given commit. The fingerprinting approach has -//! a few advantages: -//! -//! * A `DepNode` can simply be serialized to disk and loaded in another session -//! without the need to do any "rebasing" (like we have to do for Spans and -//! NodeIds) or "retracing" (like we had to do for `DefId` in earlier -//! implementations of the dependency graph). -//! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to -//! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. -//! * Since we just have a bit pattern, `DepNode` can be mapped from disk into -//! memory without any post-processing (e.g., "abomination-style" pointer -//! reconstruction). -//! * Because a `DepNode` is self-contained, we can instantiate `DepNodes` that -//! refer to things that do not exist anymore. In previous implementations -//! `DepNode` contained a `DefId`. A `DepNode` referring to something that -//! had been removed between the previous and the current compilation session -//! could not be instantiated because the current compilation session -//! contained no `DefId` for thing that had been removed. -//! -//! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro -//! defines the `DepKind` enum. Each `DepKind` has its own parameters that are -//! needed at runtime in order to construct a valid `DepNode` fingerprint. -//! However, only `CompileCodegenUnit` and `CompileMonoItem` are constructed -//! explicitly (with `make_compile_codegen_unit` cq `make_compile_mono_item`). -//! -//! Because the macro sees what parameters a given `DepKind` requires, it can -//! "infer" some properties for each kind of `DepNode`: -//! -//! * Whether a `DepNode` of a given kind has any parameters at all. Some -//! `DepNode`s could represent global concepts with only one value. -//! * Whether it is possible, in principle, to reconstruct a query key from a -//! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, -//! in which case it is possible to map the node's fingerprint back to the -//! `DefId` it was computed from. In other cases, too much information gets -//! lost during fingerprint computation. -//! -//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with -//! `DepNode::new()`, ensures that only valid `DepNode` instances can be -//! constructed. For example, the API does not allow for constructing -//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. -//! More generally speaking, it relieves the user of the `DepNode` API of -//! having to know how to compute the expected fingerprint for a given set of -//! node parameters. -//! -//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html - use rustc_data_structures::fingerprint::Fingerprint; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModDefId, ModDefId}; use rustc_hir::definitions::DefPathHash; diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 2902d17d6873..9d3368607a21 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -1,19 +1,20 @@ -//! This module defines the `DepNode` type which the compiler uses to represent -//! nodes in the dependency graph. A `DepNode` consists of a `DepKind` (which -//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) -//! and a `Fingerprint`, a 128 bit hash value the exact meaning of which +//! This module defines the [`DepNode`] type which the compiler uses to represent +//! nodes in the [dependency graph]. A `DepNode` consists of a [`DepKind`] (which +//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.) +//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which //! depends on the node's `DepKind`. Together, the kind and the fingerprint //! fully identify a dependency node, even across multiple compilation sessions. //! In other words, the value of the fingerprint does not depend on anything //! that is specific to a given compilation session, like an unpredictable -//! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a +//! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a //! pointer. The concept behind this could be compared to how git commit hashes -//! uniquely identify a given commit and has a few advantages: +//! uniquely identify a given commit. The fingerprinting approach has +//! a few advantages: //! //! * A `DepNode` can simply be serialized to disk and loaded in another session -//! without the need to do any "rebasing (like we have to do for Spans and -//! NodeIds) or "retracing" like we had to do for `DefId` in earlier -//! implementations of the dependency graph. +//! without the need to do any "rebasing" (like we have to do for Spans and +//! NodeIds) or "retracing" (like we had to do for `DefId` in earlier +//! implementations of the dependency graph). //! * A `Fingerprint` is just a bunch of bits, which allows `DepNode` to //! implement `Copy`, `Sync`, `Send`, `Freeze`, etc. //! * Since we just have a bit pattern, `DepNode` can be mapped from disk into @@ -26,10 +27,12 @@ //! could not be instantiated because the current compilation session //! contained no `DefId` for thing that had been removed. //! -//! `DepNode` definition happens in `rustc_middle` with the `define_dep_nodes!()` macro. -//! This macro defines the `DepKind` enum and a corresponding `DepConstructor` enum. The -//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at runtime in order -//! to construct a valid `DepNode` fingerprint. +//! `DepNode` definition happens in `rustc_middle` with the +//! `define_dep_nodes!()` macro. This macro defines the `DepKind` enum. Each +//! `DepKind` has its own parameters that are needed at runtime in order to +//! construct a valid `DepNode` fingerprint. However, only `CompileCodegenUnit` +//! and `CompileMonoItem` are constructed explicitly (with +//! `make_compile_codegen_unit` and `make_compile_mono_item`). //! //! Because the macro sees what parameters a given `DepKind` requires, it can //! "infer" some properties for each kind of `DepNode`: @@ -41,6 +44,16 @@ //! in which case it is possible to map the node's fingerprint back to the //! `DefId` it was computed from. In other cases, too much information gets //! lost during fingerprint computation. +//! +//! `make_compile_codegen_unit` and `make_compile_mono_items`, together with +//! `DepNode::new()`, ensure that only valid `DepNode` instances can be +//! constructed. For example, the API does not allow for constructing +//! parameterless `DepNode`s with anything other than a zeroed out fingerprint. +//! More generally speaking, it relieves the user of the `DepNode` API of +//! having to know how to compute the expected fingerprint for a given set of +//! node parameters. +//! +//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html use std::fmt; use std::hash::Hash; From f89d509eb19d7f53cba39454a446b73d0ecc2fdb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 19:36:16 +1100 Subject: [PATCH 51/68] Remove comment duplication. The same comments are on the `DepNodeExt` trait and the single impl of that trait, immediately below. This commit eliminates the duplication. --- compiler/rustc_middle/src/dep_graph/dep_node.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 9afba83a4f8d..14c72a61acd9 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -100,26 +100,14 @@ pub(crate) fn make_compile_mono_item<'tcx>( } pub trait DepNodeExt: Sized { - /// Extracts the DefId corresponding to this DepNode. This will work - /// if two conditions are met: - /// - /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and - /// 2. the item that the DefPath refers to exists in the current tcx. - /// - /// Condition (1) is determined by the DepKind variant of the - /// DepNode. Condition (2) might not be fulfilled if a DepNode - /// refers to something from the previous compilation session that - /// has been removed. fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option; - /// Used in testing fn from_label_string( tcx: TyCtxt<'_>, label: &str, def_path_hash: DefPathHash, ) -> Result; - /// Used in testing fn has_label_string(label: &str) -> bool; } From 6d03fa75192d4915c3b79ea2e4909aacd4881ebf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 2 Feb 2025 19:51:37 +1100 Subject: [PATCH 52/68] Remove `impl_for_typed_def_id` macro. It has a single call site and removing it makes the code simpler. Perhaps there were more uses at some point in the past? --- .../rustc_middle/src/dep_graph/dep_node.rs | 82 +++++++++---------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 14c72a61acd9..7525aeb92272 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -329,52 +329,46 @@ impl<'tcx> DepNodeParams> for HirId { } } -macro_rules! impl_for_typed_def_id { - ($Name:ident, $LocalName:ident) => { - impl<'tcx> DepNodeParams> for $Name { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } +impl<'tcx> DepNodeParams> for ModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - DefId::recover(tcx, dep_node).map($Name::new_unchecked) - } - } - - impl<'tcx> DepNodeParams> for $LocalName { - #[inline(always)] - fn fingerprint_style() -> FingerprintStyle { - FingerprintStyle::DefPathHash - } - - #[inline(always)] - fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { - self.to_def_id().to_fingerprint(tcx) - } - - #[inline(always)] - fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - self.to_def_id().to_debug_str(tcx) - } - - #[inline(always)] - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - LocalDefId::recover(tcx, dep_node).map($LocalName::new_unchecked) - } - } - }; + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + DefId::recover(tcx, dep_node).map(ModDefId::new_unchecked) + } } -impl_for_typed_def_id! { ModDefId, LocalModDefId } +impl<'tcx> DepNodeParams> for LocalModDefId { + #[inline(always)] + fn fingerprint_style() -> FingerprintStyle { + FingerprintStyle::DefPathHash + } + + #[inline(always)] + fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint { + self.to_def_id().to_fingerprint(tcx) + } + + #[inline(always)] + fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { + self.to_def_id().to_debug_str(tcx) + } + + #[inline(always)] + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + LocalDefId::recover(tcx, dep_node).map(LocalModDefId::new_unchecked) + } +} From 0be280e52f43b65e1f32b5f10687ce440f77070e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 08:04:54 +1100 Subject: [PATCH 53/68] Simplify `thir_with_elements` macro. The `field_name`/`field_ty` don't need to be parameters, they can be hardcoded. --- compiler/rustc_middle/src/thir.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index d56046136c7a..0236136af3f3 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -37,9 +37,6 @@ pub mod visit; macro_rules! thir_with_elements { ( - $($field_name:ident: $field_ty:ty,)* - - @elements: $($name:ident: $id:ty => $value:ty => $format:literal,)* ) => { $( @@ -55,20 +52,16 @@ macro_rules! thir_with_elements { /// This can be indexed directly by any THIR index (e.g. [`ExprId`]). #[derive(Debug, HashStable, Clone)] pub struct Thir<'tcx> { - $( - pub $field_name: $field_ty, - )* + pub body_type: BodyTy<'tcx>, $( pub $name: IndexVec<$id, $value>, )* } impl<'tcx> Thir<'tcx> { - pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> { + pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> { Thir { - $( - $field_name, - )* + body_type, $( $name: IndexVec::new(), )* @@ -88,9 +81,6 @@ macro_rules! thir_with_elements { } thir_with_elements! { - body_type: BodyTy<'tcx>, - -@elements: arms: ArmId => Arm<'tcx> => "a{}", blocks: BlockId => Block => "b{}", exprs: ExprId => Expr<'tcx> => "e{}", From bd6eb05ccd3eaff622992255144a55ddbaf328e2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 08:20:34 +1100 Subject: [PATCH 54/68] Update top-level `rustc_middle` comment. - Mention THIR. - Removed mentions of non-existent READMEs. --- compiler/rustc_middle/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 9d2aae1477b5..7a6d329fd475 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -1,10 +1,11 @@ //! The "main crate" of the Rust compiler. This crate contains common //! type definitions that are used by the other crates in the rustc -//! "family". Some prominent examples (note that each of these modules -//! has their own README with further details). +//! "family". The following are some prominent examples. //! //! - **HIR.** The "high-level (H) intermediate representation (IR)" is //! defined in the [`hir`] module. +//! - **THIR.** The "typed high-level (H) intermediate representation (IR)" +//! is defined in the [`thir`] module. //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is //! defined in the [`mir`] module. This module contains only the //! *definition* of the MIR; the passes that transform and operate From 6606bb35a97ebe14dab0ad51e234a3cd3c91fece Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 10:11:54 +1100 Subject: [PATCH 55/68] Fix an inconsistent import. --- compiler/rustc_middle/src/thir/visit.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 2aeb13942a38..13b8af55e518 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -1,8 +1,7 @@ use super::{ - AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat, - PatKind, Stmt, StmtKind, Thir, + AdtExpr, AdtExprBase, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, + Pat, PatKind, Stmt, StmtKind, Thir, }; -use crate::thir::AdtExprBase; pub trait Visitor<'thir, 'tcx: 'thir>: Sized { fn thir(&self) -> &'thir Thir<'tcx>; From d8d6128026cc09707b7520fda7d5669ad0833251 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Feb 2025 13:39:38 +1100 Subject: [PATCH 56/68] Two minor `use` fixups. I *think* this addresses what the `FIXME` comments are asking for. --- compiler/rustc_middle/src/traits/mod.rs | 3 +-- compiler/rustc_middle/src/traits/query.rs | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 28a6eba75aa5..d0ce4e6242ea 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -21,13 +21,12 @@ use rustc_macros::{ }; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_span::{DUMMY_SP, Span, Symbol}; -// FIXME: Remove this import and import via `solve::` -pub use rustc_type_ir::solve::BuiltinImplSource; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; use crate::mir::ConstraintCategory; +pub use crate::traits::solve::BuiltinImplSource; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::{self, AdtKind, GenericArgsRef, Ty}; diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index f049da95f29a..8cd04a6f5e40 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -7,11 +7,10 @@ use rustc_macros::{HashStable, TypeFoldable, TypeVisitable}; use rustc_span::Span; -// FIXME: Remove this import and import via `traits::solve`. -pub use rustc_type_ir::solve::NoSolution; use crate::error::DropCheckOverflow; use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse}; +pub use crate::traits::solve::NoSolution; use crate::ty::{self, GenericArg, Ty, TyCtxt}; pub mod type_op { From 3419e2f408dbcc0746b3b0da8016a6a48071e28a Mon Sep 17 00:00:00 2001 From: ricci009 Date: Mon, 3 Feb 2025 17:21:32 -0500 Subject: [PATCH 57/68] primitive type migration from mod.rs to primitives.rs --- library/core/src/ffi/mod.rs | 175 ++--------------------------- library/core/src/ffi/primitives.rs | 174 ++++++++++++++++++++++++++++ src/tools/tidy/src/pal.rs | 3 +- 3 files changed, 183 insertions(+), 169 deletions(-) create mode 100644 library/core/src/ffi/primitives.rs diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 51687a3adcdd..50968c57adc6 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -37,175 +37,14 @@ pub use self::va_list::{VaList, VaListImpl}; )] pub mod va_list; -macro_rules! type_alias { - { - $Docfile:tt, $Alias:ident = $Real:ty; - $( $Cfg:tt )* - } => { - #[doc = include_str!($Docfile)] - $( $Cfg )* - #[stable(feature = "core_ffi_c", since = "1.64.0")] - pub type $Alias = $Real; - } -} - -type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] } - -type_alias! { "c_schar.md", c_schar = i8; } -type_alias! { "c_uchar.md", c_uchar = u8; } -type_alias! { "c_short.md", c_short = i16; } -type_alias! { "c_ushort.md", c_ushort = u16; } - -type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] } -type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] } - -type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] } -type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] } - -type_alias! { "c_longlong.md", c_longlong = i64; } -type_alias! { "c_ulonglong.md", c_ulonglong = u64; } - -type_alias! { "c_float.md", c_float = f32; } -type_alias! { "c_double.md", c_double = f64; } - -/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). -/// -/// This type is currently always [`usize`], however in the future there may be -/// platforms where this is not the case. +mod primitives; +#[stable(feature = "core_ffi_c", since = "1.64.0")] +pub use self::primitives::{ + c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, + c_ulong, c_ulonglong, c_ushort, +}; #[unstable(feature = "c_size_t", issue = "88345")] -pub type c_size_t = usize; - -/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++). -/// -/// This type is currently always [`isize`], however in the future there may be -/// platforms where this is not the case. -#[unstable(feature = "c_size_t", issue = "88345")] -pub type c_ptrdiff_t = isize; - -/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type. -/// -/// This type is currently always [`isize`], however in the future there may be -/// platforms where this is not the case. -#[unstable(feature = "c_size_t", issue = "88345")] -pub type c_ssize_t = isize; - -mod c_char_definition { - cfg_if! { - // These are the targets on which c_char is unsigned. Usually the - // signedness is the same for all target_os values on a given architecture - // but there are some exceptions (see isSignedCharDefault() in clang). - // - // aarch64: - // Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm® - // 64-bit Architecture (AArch64) says C/C++ char is unsigned byte. - // https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings - // arm: - // Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm® - // Architecture says C/C++ char is unsigned byte. - // https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings - // csky: - // Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface - // Standards Manual says ANSI C char is unsigned byte. - // https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf - // Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945). - // hexagon: - // Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application - // Binary Interface User Guide says "By default, the `char` data type is unsigned." - // https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf - // msp430: - // Section 2.1 "Basic Types" in MSP430 Embedded Application Binary - // Interface says "The char type is unsigned by default". - // https://www.ti.com/lit/an/slaa534a/slaa534a.pdf - // powerpc/powerpc64: - // - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC - // Processor Supplement says ANSI C char is unsigned byte - // https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf - // - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application - // Binary Interface Supplement 1.9 says ANSI C is unsigned byte - // https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE - // - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification - // says char is unsigned byte - // https://openpowerfoundation.org/specifications/64bitelfabi/ - // - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char." - // https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types - // riscv32/riscv64: - // C/C++ type representations section in RISC-V Calling Conventions - // page in RISC-V ELF psABI Document says "char is unsigned." - // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations - // s390x: - // - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement - // Version 1.6.1 categorize ISO C char in unsigned integer - // https://github.com/IBM/s390x-abi/releases/tag/v1.6.1 - // - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char." - // https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types - // xtensa: - // Section 2.17.1 "Data Types and Alignment" of Xtensa LX Microprocessor Overview handbook - // says "`char` type is unsigned by default". - // https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf - // - // On the following operating systems, c_char is signed by default, regardless of architecture. - // Darwin (macOS, iOS, etc.): - // Apple targets' c_char is signed by default even on arm - // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly - // Windows: - // Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char - // are promoted to int as if from type signed char by default, unless the /J compilation - // option is used." - // https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types - // L4Re: - // The kernel builds with -funsigned-char on all targets (but useserspace follows the - // architecture defaults). As we only have a target for userspace apps so there are no - // special cases for L4Re below. - // https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240 - if #[cfg(all( - not(windows), - not(target_vendor = "apple"), - any( - target_arch = "aarch64", - target_arch = "arm", - target_arch = "csky", - target_arch = "hexagon", - target_arch = "msp430", - target_arch = "powerpc", - target_arch = "powerpc64", - target_arch = "riscv32", - target_arch = "riscv64", - target_arch = "s390x", - target_arch = "xtensa", - ) - ))] { - pub(super) type c_char = u8; - } else { - // On every other target, c_char is signed. - pub(super) type c_char = i8; - } - } -} - -mod c_int_definition { - cfg_if! { - if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { - pub(super) type c_int = i16; - pub(super) type c_uint = u16; - } else { - pub(super) type c_int = i32; - pub(super) type c_uint = u32; - } - } -} - -mod c_long_definition { - cfg_if! { - if #[cfg(all(target_pointer_width = "64", not(windows)))] { - pub(super) type c_long = i64; - pub(super) type c_ulong = u64; - } else { - // The minimal size of `long` in the C standard is 32 bits - pub(super) type c_long = i32; - pub(super) type c_ulong = u32; - } - } -} +pub use self::primitives::{c_ptrdiff_t, c_size_t, c_ssize_t}; // N.B., for LLVM to recognize the void pointer type and by extension // functions like malloc(), we need to have it represented as i8* in diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs new file mode 100644 index 000000000000..ece3c7538dab --- /dev/null +++ b/library/core/src/ffi/primitives.rs @@ -0,0 +1,174 @@ +//! Defines primitive types that match C's type definitions for FFI compatibility. +//! +//! This module is intentionally standalone to facilitate parsing when retrieving +//! core C types. + +macro_rules! type_alias { + { + $Docfile:tt, $Alias:ident = $Real:ty; + $( $Cfg:tt )* + } => { + #[doc = include_str!($Docfile)] + $( $Cfg )* + #[stable(feature = "core_ffi_c", since = "1.64.0")] + pub type $Alias = $Real; + } +} + +type_alias! { "c_char.md", c_char = c_char_definition::c_char; #[doc(cfg(all()))] } + +type_alias! { "c_schar.md", c_schar = i8; } +type_alias! { "c_uchar.md", c_uchar = u8; } +type_alias! { "c_short.md", c_short = i16; } +type_alias! { "c_ushort.md", c_ushort = u16; } + +type_alias! { "c_int.md", c_int = c_int_definition::c_int; #[doc(cfg(all()))] } +type_alias! { "c_uint.md", c_uint = c_int_definition::c_uint; #[doc(cfg(all()))] } + +type_alias! { "c_long.md", c_long = c_long_definition::c_long; #[doc(cfg(all()))] } +type_alias! { "c_ulong.md", c_ulong = c_long_definition::c_ulong; #[doc(cfg(all()))] } + +type_alias! { "c_longlong.md", c_longlong = i64; } +type_alias! { "c_ulonglong.md", c_ulonglong = u64; } + +type_alias! { "c_float.md", c_float = f32; } +type_alias! { "c_double.md", c_double = f64; } + +mod c_char_definition { + cfg_if! { + // These are the targets on which c_char is unsigned. Usually the + // signedness is the same for all target_os values on a given architecture + // but there are some exceptions (see isSignedCharDefault() in clang). + // + // aarch64: + // Section 10 "Arm C and C++ language mappings" in Procedure Call Standard for the Arm® + // 64-bit Architecture (AArch64) says C/C++ char is unsigned byte. + // https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs64/aapcs64.rst#arm-c-and-c-language-mappings + // arm: + // Section 8 "Arm C and C++ Language Mappings" in Procedure Call Standard for the Arm® + // Architecture says C/C++ char is unsigned byte. + // https://github.com/ARM-software/abi-aa/blob/2024Q3/aapcs32/aapcs32.rst#arm-c-and-c-language-mappings + // csky: + // Section 2.1.2 "Primary Data Type" in C-SKY V2 CPU Applications Binary Interface + // Standards Manual says ANSI C char is unsigned byte. + // https://github.com/c-sky/csky-doc/blob/9f7121f7d40970ba5cc0f15716da033db2bb9d07/C-SKY_V2_CPU_Applications_Binary_Interface_Standards_Manual.pdf + // Note: this doesn't seem to match Clang's default (https://github.com/rust-lang/rust/issues/129945). + // hexagon: + // Section 3.1 "Basic data type" in Qualcomm Hexagon™ Application + // Binary Interface User Guide says "By default, the `char` data type is unsigned." + // https://docs.qualcomm.com/bundle/publicresource/80-N2040-23_REV_K_Qualcomm_Hexagon_Application_Binary_Interface_User_Guide.pdf + // msp430: + // Section 2.1 "Basic Types" in MSP430 Embedded Application Binary + // Interface says "The char type is unsigned by default". + // https://www.ti.com/lit/an/slaa534a/slaa534a.pdf + // powerpc/powerpc64: + // - PPC32 SysV: "Table 3-1 Scalar Types" in System V Application Binary Interface PowerPC + // Processor Supplement says ANSI C char is unsigned byte + // https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf + // - PPC64 ELFv1: Section 3.1.4 "Fundamental Types" in 64-bit PowerPC ELF Application + // Binary Interface Supplement 1.9 says ANSI C is unsigned byte + // https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUND-TYPE + // - PPC64 ELFv2: Section 2.1.2.2 "Fundamental Types" in 64-Bit ELF V2 ABI Specification + // says char is unsigned byte + // https://openpowerfoundation.org/specifications/64bitelfabi/ + // - AIX: XL C for AIX Language Reference says "By default, char behaves like an unsigned char." + // https://www.ibm.com/docs/en/xl-c-aix/13.1.3?topic=specifiers-character-types + // riscv32/riscv64: + // C/C++ type representations section in RISC-V Calling Conventions + // page in RISC-V ELF psABI Document says "char is unsigned." + // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/draft-20240829-13bfa9f54634cb60d86b9b333e109f077805b4b3/riscv-cc.adoc#cc-type-representations + // s390x: + // - ELF: "Table 1.1.: Scalar types" in ELF Application Binary Interface s390x Supplement + // Version 1.6.1 categorize ISO C char in unsigned integer + // https://github.com/IBM/s390x-abi/releases/tag/v1.6.1 + // - z/OS: XL C/C++ Language Reference says: "By default, char behaves like an unsigned char." + // https://www.ibm.com/docs/en/zos/3.1.0?topic=specifiers-character-types + // xtensa: + // Section 2.17.1 "Data Types and Alignment" of Xtensa LX Microprocessor Overview handbook + // says "`char` type is unsigned by default". + // https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf + // + // On the following operating systems, c_char is signed by default, regardless of architecture. + // Darwin (macOS, iOS, etc.): + // Apple targets' c_char is signed by default even on arm + // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Handle-data-types-and-data-alignment-properly + // Windows: + // Windows MSVC C++ Language Reference says "Microsoft-specific: Variables of type char + // are promoted to int as if from type signed char by default, unless the /J compilation + // option is used." + // https://learn.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-170#character-types + // L4Re: + // The kernel builds with -funsigned-char on all targets (but useserspace follows the + // architecture defaults). As we only have a target for userspace apps so there are no + // special cases for L4Re below. + // https://github.com/rust-lang/rust/pull/132975#issuecomment-2484645240 + if #[cfg(all( + not(windows), + not(target_vendor = "apple"), + any( + target_arch = "aarch64", + target_arch = "arm", + target_arch = "csky", + target_arch = "hexagon", + target_arch = "msp430", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "s390x", + target_arch = "xtensa", + ) + ))] { + pub(super) type c_char = u8; + } else { + // On every other target, c_char is signed. + pub(super) type c_char = i8; + } + } +} + +mod c_long_definition { + cfg_if! { + if #[cfg(all(target_pointer_width = "64", not(windows)))] { + pub(super) type c_long = i64; + pub(super) type c_ulong = u64; + } else { + // The minimal size of `long` in the C standard is 32 bits + pub(super) type c_long = i32; + pub(super) type c_ulong = u32; + } + } +} + +/// Equivalent to C's `size_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`usize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_size_t = usize; + +/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++). +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_ptrdiff_t = isize; + +/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type. +/// +/// This type is currently always [`isize`], however in the future there may be +/// platforms where this is not the case. +#[unstable(feature = "c_size_t", issue = "88345")] +pub type c_ssize_t = isize; + +mod c_int_definition { + cfg_if! { + if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { + pub(super) type c_int = i16; + pub(super) type c_uint = u16; + } else { + pub(super) type c_int = i32; + pub(super) type c_uint = u32; + } + } +} diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index c650fd0eec6d..c708ff7150c9 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -48,8 +48,9 @@ const EXCEPTION_PATHS: &[&str] = &[ // we must use `#[cfg(windows)]` to conditionally compile the // correct `VaList` structure for windows. "library/core/src/ffi/va_list.rs", - // We placed a linkage against Windows libraries here + // core::ffi contains platform-specific type and linkage configuration "library/core/src/ffi/mod.rs", + "library/core/src/ffi/primitives.rs", "library/std/src/sys", // Platform-specific code for std lives here. "library/std/src/os", // Platform-specific public interfaces // Temporary `std` exceptions From d47cb21188ad1356fa7305ab2b87a7108c86abcd Mon Sep 17 00:00:00 2001 From: Urgau Date: Mon, 3 Feb 2025 23:59:43 +0100 Subject: [PATCH 58/68] Add note about `FnPtr` being exposed as public bound --- library/core/src/marker.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 01af964a83e2..c99feaca055a 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1070,6 +1070,9 @@ marker_impls! { } /// A common trait implemented by all function pointers. +// +// Note that while the trait is internal and unstable it is nevertheless +// exposed as a public bound of the stable `core::ptr::fn_addr_eq` function. #[unstable( feature = "fn_ptr_trait", issue = "none", From 36839759ce535c0496b8060c3d4beb41a170dd6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Feb 2025 19:00:20 +0000 Subject: [PATCH 59/68] Add missing lang items in no_core tests in rustdoc --- tests/rustdoc-json/primitives/primitive_impls.rs | 5 ++++- tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs | 5 ++++- tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr | 4 ++-- tests/rustdoc/cfg_doc_reexport.rs | 5 ++++- tests/rustdoc/cross-crate-primitive-doc.rs | 5 ++++- tests/rustdoc/intra-doc/no-doc-primitive.rs | 5 +++++ tests/rustdoc/reexport-trait-from-hidden-111064-2.rs | 5 ++++- tests/rustdoc/safe-intrinsic.rs | 5 ++++- 8 files changed, 31 insertions(+), 8 deletions(-) diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs index 77d1d68f8e4e..58c222ce4f0b 100644 --- a/tests/rustdoc-json/primitives/primitive_impls.rs +++ b/tests/rustdoc-json/primitives/primitive_impls.rs @@ -1,4 +1,4 @@ -#![feature(no_core)] +#![feature(no_core, lang_items)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] #![no_core] @@ -6,6 +6,9 @@ //@ set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id" +#[lang = "sized"] +trait Sized {} + /// Only core can do this impl i32 { //@ set identity = "$.index[*][?(@.docs=='Do Nothing')].id" diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs index 6b1aa455d981..18ac37280c0e 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.rs @@ -2,9 +2,12 @@ // feature. #![deny(warnings)] -#![feature(no_core)] +#![feature(no_core, lang_items)] #![no_core] +#[lang = "sized"] +trait Sized {} + /// ```{class="} /// main; /// ``` diff --git a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr index 385b2ccacc1b..cc13cc0fe531 100644 --- a/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr +++ b/tests/rustdoc-ui/custom_code_classes_in_docs-warning3.stderr @@ -1,5 +1,5 @@ error: unclosed quote string `"` - --> $DIR/custom_code_classes_in_docs-warning3.rs:8:1 + --> $DIR/custom_code_classes_in_docs-warning3.rs:11:1 | LL | / /// ```{class="} LL | | /// main; @@ -17,7 +17,7 @@ LL | #![deny(warnings)] = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` error: unclosed quote string `"` - --> $DIR/custom_code_classes_in_docs-warning3.rs:8:1 + --> $DIR/custom_code_classes_in_docs-warning3.rs:11:1 | LL | / /// ```{class="} LL | | /// main; diff --git a/tests/rustdoc/cfg_doc_reexport.rs b/tests/rustdoc/cfg_doc_reexport.rs index f8101e2a9580..44ec36632841 100644 --- a/tests/rustdoc/cfg_doc_reexport.rs +++ b/tests/rustdoc/cfg_doc_reexport.rs @@ -1,9 +1,12 @@ #![feature(doc_cfg)] -#![feature(no_core)] +#![feature(no_core, lang_items)] #![crate_name = "foo"] #![no_core] +#[lang = "sized"] +trait Sized {} + //@ has 'foo/index.html' //@ has - '//dt/*[@class="stab portability"]' 'foobar' //@ has - '//dt/*[@class="stab portability"]' 'bar' diff --git a/tests/rustdoc/cross-crate-primitive-doc.rs b/tests/rustdoc/cross-crate-primitive-doc.rs index ca33dedcbaec..0ffde5b0f2d8 100644 --- a/tests/rustdoc/cross-crate-primitive-doc.rs +++ b/tests/rustdoc/cross-crate-primitive-doc.rs @@ -2,9 +2,12 @@ //@ compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options //@ only-linux -#![feature(no_core)] +#![feature(no_core, lang_items)] #![no_core] +#[lang = "sized"] +trait Sized {} + extern crate primitive_doc; //@ has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize' diff --git a/tests/rustdoc/intra-doc/no-doc-primitive.rs b/tests/rustdoc/intra-doc/no-doc-primitive.rs index 1f8622ab867c..79825643b98c 100644 --- a/tests/rustdoc/intra-doc/no-doc-primitive.rs +++ b/tests/rustdoc/intra-doc/no-doc-primitive.rs @@ -6,8 +6,13 @@ #![rustc_coherence_is_core] #![crate_type = "rlib"] + //@ has no_doc_primitive/index.html //! A [`char`] and its [`char::len_utf8`]. + +#[lang = "sized"] +trait Sized {} + impl char { pub fn len_utf8(self) -> usize { 42 diff --git a/tests/rustdoc/reexport-trait-from-hidden-111064-2.rs b/tests/rustdoc/reexport-trait-from-hidden-111064-2.rs index 2b21f9862b44..61060b3ff7c7 100644 --- a/tests/rustdoc/reexport-trait-from-hidden-111064-2.rs +++ b/tests/rustdoc/reexport-trait-from-hidden-111064-2.rs @@ -1,8 +1,11 @@ // Regression test for . -#![feature(no_core)] +#![feature(no_core, lang_items)] #![no_core] #![crate_name = "foo"] +#[lang = "sized"] +trait Sized {} + //@ files "foo" "['sidebar-items.js', 'all.html', 'hidden', 'index.html', 'struct.Bar.html', \ // 'visible']" //@ files "foo/hidden" "['inner']" diff --git a/tests/rustdoc/safe-intrinsic.rs b/tests/rustdoc/safe-intrinsic.rs index 07af04ace603..1edc1d9f79b9 100644 --- a/tests/rustdoc/safe-intrinsic.rs +++ b/tests/rustdoc/safe-intrinsic.rs @@ -1,10 +1,13 @@ #![feature(intrinsics)] -#![feature(no_core)] +#![feature(no_core, lang_items)] #![feature(rustc_attrs)] #![no_core] #![crate_name = "foo"] +#[lang = "sized"] +trait Sized {} + //@ has 'foo/fn.abort.html' //@ has - '//pre[@class="rust item-decl"]' 'pub fn abort() -> !' #[rustc_intrinsic] From 0b26dc0b51c87a90ce61f50dd7141ff451513b23 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Feb 2025 01:50:31 +0000 Subject: [PATCH 60/68] Remove unnecessary layout assertions for object-safe receivers --- .../src/traits/dyn_compatibility.rs | 107 +----------------- tests/crashes/125810.rs | 10 -- tests/crashes/90110.rs | 57 ---------- tests/ui/self/dispatch-from-dyn-layout-2.rs | 16 +++ tests/ui/self/dispatch-from-dyn-layout-3.rs | 19 ++++ .../self/dispatch-from-dyn-layout.rs} | 6 +- 6 files changed, 42 insertions(+), 173 deletions(-) delete mode 100644 tests/crashes/125810.rs delete mode 100644 tests/crashes/90110.rs create mode 100644 tests/ui/self/dispatch-from-dyn-layout-2.rs create mode 100644 tests/ui/self/dispatch-from-dyn-layout-3.rs rename tests/{crashes/57276.rs => ui/self/dispatch-from-dyn-layout.rs} (54%) diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index baa94ead9d48..617bc87a9d23 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -4,19 +4,16 @@ //! //! [^1]: Formerly known as "object safety". -use std::iter; use std::ops::ControlFlow; -use rustc_abi::BackendRepr; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, ExistentialPredicateStableCmpExt as _, GenericArgs, Ty, TyCtxt, - TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, TypeVisitor, TypingMode, Upcast, + self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; use rustc_type_ir::elaborate; @@ -109,14 +106,6 @@ fn dyn_compatibility_violations_for_trait( violations.push(DynCompatibilityViolation::SupertraitNonLifetimeBinder(spans)); } - if violations.is_empty() { - for item in tcx.associated_items(trait_def_id).in_definition_order() { - if let ty::AssocKind::Fn = item.kind { - check_receiver_correct(tcx, trait_def_id, *item); - } - } - } - violations } @@ -499,55 +488,6 @@ fn virtual_call_violations_for_method<'tcx>( errors } -/// This code checks that `receiver_is_dispatchable` is correctly implemented. -/// -/// This check is outlined from the dyn-compatibility check to avoid cycles with -/// layout computation, which relies on knowing whether methods are dyn-compatible. -fn check_receiver_correct<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, method: ty::AssocItem) { - if !is_vtable_safe_method(tcx, trait_def_id, method) { - return; - } - - let method_def_id = method.def_id; - let sig = tcx.fn_sig(method_def_id).instantiate_identity(); - let typing_env = ty::TypingEnv::non_body_analysis(tcx, method_def_id); - let receiver_ty = tcx.liberate_late_bound_regions(method_def_id, sig.input(0)); - - if receiver_ty == tcx.types.self_param { - // Assumed OK, may change later if unsized_locals permits `self: Self` as dispatchable. - return; - } - - // e.g., `Rc<()>` - let unit_receiver_ty = receiver_for_self_ty(tcx, receiver_ty, tcx.types.unit, method_def_id); - match tcx.layout_of(typing_env.as_query_input(unit_receiver_ty)).map(|l| l.backend_repr) { - Ok(BackendRepr::Scalar(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method_def_id), - format!("receiver {unit_receiver_ty:?} when `Self = ()` should have a Scalar ABI; found {abi:?}"), - ); - } - } - - let trait_object_ty = object_ty_for_trait(tcx, trait_def_id, tcx.lifetimes.re_static); - - // e.g., `Rc` - let trait_object_receiver = - receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method_def_id); - match tcx.layout_of(typing_env.as_query_input(trait_object_receiver)).map(|l| l.backend_repr) { - Ok(BackendRepr::ScalarPair(..)) => (), - abi => { - tcx.dcx().span_delayed_bug( - tcx.def_span(method_def_id), - format!( - "receiver {trait_object_receiver:?} when `Self = {trait_object_ty}` should have a ScalarPair ABI; found {abi:?}" - ), - ); - } - } -} - /// Performs a type instantiation to produce the version of `receiver_ty` when `Self = self_ty`. /// For example, for `receiver_ty = Rc` and `self_ty = Foo`, returns `Rc`. fn receiver_for_self_ty<'tcx>( @@ -569,49 +509,6 @@ fn receiver_for_self_ty<'tcx>( result } -/// Creates the object type for the current trait. For example, -/// if the current trait is `Deref`, then this will be -/// `dyn Deref + 'static`. -#[instrument(level = "trace", skip(tcx), ret)] -fn object_ty_for_trait<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - lifetime: ty::Region<'tcx>, -) -> Ty<'tcx> { - let trait_ref = ty::TraitRef::identity(tcx, trait_def_id); - debug!(?trait_ref); - - let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait( - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), - )); - debug!(?trait_predicate); - - let pred: ty::Predicate<'tcx> = trait_ref.upcast(tcx); - let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred]) - .filter_map(|pred| { - debug!(?pred); - let pred = pred.as_projection_clause()?; - Some(pred.map_bound(|p| { - ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty( - tcx, p, - )) - })) - }) - .collect(); - // NOTE: Since #37965, the existential predicates list has depended on the - // list of predicates to be sorted. This is mostly to enforce that the primary - // predicate comes first. - elaborated_predicates.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); - elaborated_predicates.dedup(); - - let existential_predicates = tcx.mk_poly_existential_predicates_from_iter( - iter::once(trait_predicate).chain(elaborated_predicates), - ); - debug!(?existential_predicates); - - Ty::new_dynamic(tcx, existential_predicates, lifetime, ty::Dyn) -} - /// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type /// in the following way: diff --git a/tests/crashes/125810.rs b/tests/crashes/125810.rs deleted file mode 100644 index 4a152da8ddf3..000000000000 --- a/tests/crashes/125810.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: rust-lang/rust#125810 -#![feature(arbitrary_self_types, dispatch_from_dyn)] - -use std::ops::{Deref, DispatchFromDyn}; - -trait Trait + DispatchFromDyn> { - fn MONO_BUF(self: T) -> dyn Trait; -} - -fn main() {} diff --git a/tests/crashes/90110.rs b/tests/crashes/90110.rs deleted file mode 100644 index a27a1f42b7af..000000000000 --- a/tests/crashes/90110.rs +++ /dev/null @@ -1,57 +0,0 @@ -//@ known-bug: #90110 - -use std::fs::File; -use std::io::{BufReader, BufRead}; -use std::str::Split; -use std::path::Path; - -pub trait Parser -where dyn Parser: Sized -{ - fn new(split_header: Split<&str>) -> Self where Self: Sized; - fn parse_line(&self, split_line: &Split<&str>) -> D; -} - - -pub struct CsvReader { - parser: Box>, - - reader: BufReader, - buf: String, // Buffer we will read into. Avoids re-allocation on each line. - path: String, // Record this so we can return more informative error messages. - line: usize, // Same motivation for this. -} - -impl CsvReader -where dyn Parser: Sized -{ - fn new(path: &str, make_parser: F) -> CsvReader - where F: Fn(Split) -> dyn Parser { - let file = match File::open(Path::new(path)) { - Err(err) => panic!("Couldn't read {}: {}", path, err), - Ok(file) => file, - }; - - let mut reader = BufReader::new(file); - - let mut buf = String::new(); - - let parser = Box::new(match reader.read_line(&mut buf) { - Err(err) => panic!("Failed to read the header line from {}: {}", path, err), - Ok(_) => { - let split_header = buf.split(','); - make_parser(split_header) - }, - }); - - CsvReader { - parser: parser, - reader, - buf, - path: path.to_string(), - line: 2, - } - } -} - -pub fn main() {} diff --git a/tests/ui/self/dispatch-from-dyn-layout-2.rs b/tests/ui/self/dispatch-from-dyn-layout-2.rs new file mode 100644 index 000000000000..cd52f060dc83 --- /dev/null +++ b/tests/ui/self/dispatch-from-dyn-layout-2.rs @@ -0,0 +1,16 @@ +//@ check-pass +// Regression test for #90110. + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `Sized` predicates. + +trait Parser +where + for<'a> (dyn Parser + 'a): Sized, +{ + fn parse_line(&self); +} + +fn foo(_: &dyn Parser) {} + +fn main() {} diff --git a/tests/ui/self/dispatch-from-dyn-layout-3.rs b/tests/ui/self/dispatch-from-dyn-layout-3.rs new file mode 100644 index 000000000000..6878a4f4ac27 --- /dev/null +++ b/tests/ui/self/dispatch-from-dyn-layout-3.rs @@ -0,0 +1,19 @@ +//@ check-pass + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `DispatchFromDyn` predicates. + +#![feature(dispatch_from_dyn)] +#![feature(arbitrary_self_types)] + +use std::ops::Deref; +use std::ops::DispatchFromDyn; + +trait Trait> +where + for<'a> &'a T: DispatchFromDyn<&'a T>, +{ + fn foo(self: &T) -> Box>; +} + +fn main() {} diff --git a/tests/crashes/57276.rs b/tests/ui/self/dispatch-from-dyn-layout.rs similarity index 54% rename from tests/crashes/57276.rs rename to tests/ui/self/dispatch-from-dyn-layout.rs index f70be4fba6d8..468dc89a73e6 100644 --- a/tests/crashes/57276.rs +++ b/tests/ui/self/dispatch-from-dyn-layout.rs @@ -1,4 +1,8 @@ -//@ known-bug: #57276 +//@ check-pass +// Regression test for #57276. + +// Make sure that object safety checking doesn't freak out when +// we have impossible-to-satisfy `DispatchFromDyn` predicates. #![feature(arbitrary_self_types, dispatch_from_dyn)] From 8b1c28fdd0716e16a8d1776b40d2896128dd7654 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 3 Feb 2025 19:17:46 -0500 Subject: [PATCH 61/68] Fix ICE when function argument mismatches. --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 5 +- tests/crashes/135124.rs | 9 ---- tests/ui/fn/error-recovery-mismatch.rs | 20 ++++++++ tests/ui/fn/error-recovery-mismatch.stderr | 46 +++++++++++++++++++ 4 files changed, 70 insertions(+), 10 deletions(-) delete mode 100644 tests/crashes/135124.rs create mode 100644 tests/ui/fn/error-recovery-mismatch.rs create mode 100644 tests/ui/fn/error-recovery-mismatch.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e30c0e115dc2..e90474cabb42 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -126,7 +126,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(guar) => Err(guar), }; if let Err(guar) = has_error { - let err_inputs = self.err_args(args_no_rcvr.len(), guar); + let err_inputs = self.err_args( + method.map_or(args_no_rcvr.len(), |method| method.sig.inputs().len() - 1), + guar, + ); let err_output = Ty::new_error(self.tcx, guar); let err_inputs = match tuple_arguments { diff --git a/tests/crashes/135124.rs b/tests/crashes/135124.rs deleted file mode 100644 index d6655cb46fac..000000000000 --- a/tests/crashes/135124.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ known-bug: #135124 -trait A { - fn y(&self) - { - fn call() -> impl Sized {} - self.fold(call()); - } - fn fold(&self, &self._) {} -} diff --git a/tests/ui/fn/error-recovery-mismatch.rs b/tests/ui/fn/error-recovery-mismatch.rs new file mode 100644 index 000000000000..a50a30c8c78a --- /dev/null +++ b/tests/ui/fn/error-recovery-mismatch.rs @@ -0,0 +1,20 @@ +// Used to ICE due to a size mismatch between the actual fake signature of `fold` and the +// generated signature used reporting the parameter mismatch at the call site. +// See issue #135124 + +trait A { + fn y(&self) + { + fn call() -> impl Sized {} + self.fold(call(), call()); + } + fn fold(&self, _: T, &self._) {} + //~^ ERROR unexpected `self` parameter in function + //~| ERROR expected one of `)` or `,`, found `.` + //~| ERROR identifier `self` is bound more than once in this parameter list + //~| WARNING anonymous parameters are deprecated + //~| WARNING this is accepted in the current edition + //~| ERROR the placeholder `_` is not allowed within types +} + +fn main() {} diff --git a/tests/ui/fn/error-recovery-mismatch.stderr b/tests/ui/fn/error-recovery-mismatch.stderr new file mode 100644 index 000000000000..ad4652c11c12 --- /dev/null +++ b/tests/ui/fn/error-recovery-mismatch.stderr @@ -0,0 +1,46 @@ +error: unexpected `self` parameter in function + --> $DIR/error-recovery-mismatch.rs:11:29 + | +LL | fn fold(&self, _: T, &self._) {} + | ^^^^^ must be the first parameter of an associated function + +error: expected one of `)` or `,`, found `.` + --> $DIR/error-recovery-mismatch.rs:11:34 + | +LL | fn fold(&self, _: T, &self._) {} + | ^ + | | + | expected one of `)` or `,` + | help: missing `,` + +error[E0415]: identifier `self` is bound more than once in this parameter list + --> $DIR/error-recovery-mismatch.rs:11:30 + | +LL | fn fold(&self, _: T, &self._) {} + | ^^^^ used as parameter more than once + +warning: anonymous parameters are deprecated and will be removed in the next edition + --> $DIR/error-recovery-mismatch.rs:11:35 + | +LL | fn fold(&self, _: T, &self._) {} + | ^ help: try naming the parameter or explicitly ignoring it: `_: _` + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018! + = note: for more information, see issue #41686 + = note: `#[warn(anonymous_parameters)]` on by default + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/error-recovery-mismatch.rs:11:35 + | +LL | fn fold(&self, _: T, &self._) {} + | ^ not allowed in type signatures + | +help: use type parameters instead + | +LL | fn fold(&self, _: T, &self.U) {} + | +++ ~ + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0121, E0415. +For more information about an error, try `rustc --explain E0121`. From c4888de68eec3f392c966c492a779400374bb89f Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 4 Feb 2025 15:59:58 +1100 Subject: [PATCH 62/68] Remove helper trait `UserAnnotatedTyHelpers` This trait doesn't appear to provide any benefit over a simple helper function. --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 80 +++++++++---------- compiler/rustc_mir_build/src/thir/cx/mod.rs | 16 ++-- .../rustc_mir_build/src/thir/pattern/mod.rs | 34 +++----- compiler/rustc_mir_build/src/thir/util.rs | 44 +++++----- 4 files changed, 74 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 795ac6b4bea5..8eec0fe12d41 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -22,7 +22,6 @@ use rustc_span::{Span, sym}; use tracing::{debug, info, instrument, trace}; use crate::thir::cx::Cx; -use crate::thir::util::UserAnnotatedTyHelpers; impl<'tcx> Cx<'tcx> { /// Create a THIR expression for the given HIR expression. This expands all @@ -142,9 +141,9 @@ impl<'tcx> Cx<'tcx> { Adjust::Deref(Some(deref)) => { // We don't need to do call adjust_span here since // deref coercions always start with a built-in deref. - let call_def_id = deref.method_call(self.tcx()); + let call_def_id = deref.method_call(self.tcx); let overloaded_callee = - Ty::new_fn_def(self.tcx(), call_def_id, self.tcx().mk_args(&[expr.ty.into()])); + Ty::new_fn_def(self.tcx, call_def_id, self.tcx.mk_args(&[expr.ty.into()])); expr = Expr { temp_lifetime, @@ -253,10 +252,10 @@ impl<'tcx> Cx<'tcx> { // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). - if self.typeck_results().is_coercion_cast(source.hir_id) { + if self.typeck_results.is_coercion_cast(source.hir_id) { // Convert the lexpr to a vexpr. ExprKind::Use { source: self.mirror_expr(source) } - } else if self.typeck_results().expr_ty(source).is_ref() { + } else if self.typeck_results.expr_ty(source).is_ref() { // Special cased so that we can type check that the element // type of the source matches the pointed to type of the // destination. @@ -266,8 +265,8 @@ impl<'tcx> Cx<'tcx> { is_from_as_cast: true, } } else if let hir::ExprKind::Path(ref qpath) = source.kind - && let res = self.typeck_results().qpath_res(qpath, source.hir_id) - && let ty = self.typeck_results().node_type(source.hir_id) + && let res = self.typeck_results.qpath_res(qpath, source.hir_id) + && let ty = self.typeck_results.node_type(source.hir_id) && let ty::Adt(adt_def, args) = ty.kind() && let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), variant_ctor_id) = res { @@ -330,7 +329,7 @@ impl<'tcx> Cx<'tcx> { #[instrument(level = "debug", skip(self), ret)] fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let tcx = self.tcx; - let expr_ty = self.typeck_results().expr_ty(expr); + let expr_ty = self.typeck_results.expr_ty(expr); let (temp_lifetime, backwards_incompatible) = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); @@ -354,7 +353,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Call(fun, ref args) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and // build the appropriate UFCS call expression with the @@ -364,7 +363,7 @@ impl<'tcx> Cx<'tcx> { let method = self.method_callee(expr, fun.span, None); - let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e)); + let arg_tys = args.iter().map(|e| self.typeck_results.expr_ty_adjusted(e)); let tupled_args = Expr { ty: Ty::new_tup_from_iter(tcx, arg_tys), temp_lifetime: TempLifetime { temp_lifetime, backwards_incompatible }, @@ -380,7 +379,7 @@ impl<'tcx> Cx<'tcx> { from_hir_call: true, fn_span: expr.span, } - } else if let ty::FnDef(def_id, _) = self.typeck_results().expr_ty(fun).kind() + } else if let ty::FnDef(def_id, _) = self.typeck_results.expr_ty(fun).kind() && let Some(intrinsic) = self.tcx.intrinsic(def_id) && intrinsic.name == sym::box_new { @@ -413,7 +412,7 @@ impl<'tcx> Cx<'tcx> { }, hir::QPath::TypeRelative(_ty, _) => { if let Some((DefKind::Ctor(_, CtorKind::Fn), ctor_id)) = - self.typeck_results().type_dependent_def(fun.hir_id) + self.typeck_results.type_dependent_def(fun.hir_id) { Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) } else { @@ -426,8 +425,8 @@ impl<'tcx> Cx<'tcx> { None }; if let Some((adt_def, index)) = adt_data { - let node_args = self.typeck_results().node_args(fun.hir_id); - let user_provided_types = self.typeck_results().user_provided_types(); + let node_args = self.typeck_results.node_args(fun.hir_id); + let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { if let ty::UserTypeKind::TypeOf(ref mut did, _) = @@ -457,7 +456,7 @@ impl<'tcx> Cx<'tcx> { })) } else { ExprKind::Call { - ty: self.typeck_results().node_type(fun.hir_id), + ty: self.typeck_results.node_type(fun.hir_id), fun: self.mirror_expr(fun), args: self.mirror_exprs(args), from_hir_call: true, @@ -482,7 +481,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::AssignOp(op, lhs, rhs) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let lhs = self.mirror_expr(lhs); let rhs = self.mirror_expr(rhs); self.overloaded_operator(expr, Box::new([lhs, rhs])) @@ -498,7 +497,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Lit(lit) => ExprKind::Literal { lit, neg: false }, hir::ExprKind::Binary(op, lhs, rhs) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let lhs = self.mirror_expr(lhs); let rhs = self.mirror_expr(rhs); self.overloaded_operator(expr, Box::new([lhs, rhs])) @@ -527,7 +526,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Index(lhs, index, brackets_span) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let lhs = self.mirror_expr(lhs); let index = self.mirror_expr(index); self.overloaded_place( @@ -543,7 +542,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Unary(hir::UnOp::Deref, arg) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_place(expr, expr_ty, None, Box::new([arg]), expr.span) } else { @@ -552,7 +551,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Unary(hir::UnOp::Not, arg) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_operator(expr, Box::new([arg])) } else { @@ -561,7 +560,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Unary(hir::UnOp::Neg, arg) => { - if self.typeck_results().is_method_call(expr) { + if self.typeck_results.is_method_call(expr) { let arg = self.mirror_expr(arg); self.overloaded_operator(expr, Box::new([arg])) } else if let hir::ExprKind::Lit(lit) = arg.kind { @@ -574,7 +573,7 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Struct(qpath, fields, ref base) => match expr_ty.kind() { ty::Adt(adt, args) => match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { - let user_provided_types = self.typeck_results().user_provided_types(); + let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new); debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); ExprKind::Adt(Box::new(AdtExpr { @@ -586,15 +585,14 @@ impl<'tcx> Cx<'tcx> { base: match base { hir::StructTailExpr::Base(base) => AdtExprBase::Base(FruInfo { base: self.mirror_expr(base), - field_types: self.typeck_results().fru_field_types() - [expr.hir_id] + field_types: self.typeck_results.fru_field_types()[expr.hir_id] .iter() .copied() .collect(), }), hir::StructTailExpr::DefaultFields(_) => { AdtExprBase::DefaultFields( - self.typeck_results().fru_field_types()[expr.hir_id] + self.typeck_results.fru_field_types()[expr.hir_id] .iter() .copied() .collect(), @@ -605,7 +603,7 @@ impl<'tcx> Cx<'tcx> { })) } AdtKind::Enum => { - let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + let res = self.typeck_results.qpath_res(qpath, expr.hir_id); match res { Res::Def(DefKind::Variant, variant_id) => { assert!(matches!( @@ -615,8 +613,7 @@ impl<'tcx> Cx<'tcx> { )); let index = adt.variant_index_with_id(variant_id); - let user_provided_types = - self.typeck_results().user_provided_types(); + let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new); debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty); @@ -629,8 +626,7 @@ impl<'tcx> Cx<'tcx> { base: match base { hir::StructTailExpr::DefaultFields(_) => { AdtExprBase::DefaultFields( - self.typeck_results().fru_field_types() - [expr.hir_id] + self.typeck_results.fru_field_types()[expr.hir_id] .iter() .copied() .collect(), @@ -655,7 +651,7 @@ impl<'tcx> Cx<'tcx> { }, hir::ExprKind::Closure { .. } => { - let closure_ty = self.typeck_results().expr_ty(expr); + let closure_ty = self.typeck_results.expr_ty(expr); let (def_id, args, movability) = match *closure_ty.kind() { ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None), ty::Coroutine(def_id, args) => { @@ -703,7 +699,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Path(ref qpath) => { - let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + let res = self.typeck_results.qpath_res(qpath, expr.hir_id); self.convert_path_expr(expr, res) } @@ -772,7 +768,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::ConstBlock(ref anon_const) => { - let ty = self.typeck_results().node_type(anon_const.hir_id); + let ty = self.typeck_results.node_type(anon_const.hir_id); let did = anon_const.def_id.to_def_id(); let typeck_root_def_id = tcx.typeck_root_def_id(did); let parent_args = @@ -783,7 +779,7 @@ impl<'tcx> Cx<'tcx> { } // Now comes the rote stuff: hir::ExprKind::Repeat(v, _) => { - let ty = self.typeck_results().expr_ty(expr); + let ty = self.typeck_results.expr_ty(expr); let ty::Array(_, count) = ty.kind() else { span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty); }; @@ -837,7 +833,7 @@ impl<'tcx> Cx<'tcx> { match_source, }, hir::ExprKind::Loop(body, ..) => { - let block_ty = self.typeck_results().node_type(body.hir_id); + let block_ty = self.typeck_results.node_type(body.hir_id); let (temp_lifetime, backwards_incompatible) = self .rvalue_scopes .temporary_scope(self.region_scope_tree, body.hir_id.local_id); @@ -957,7 +953,7 @@ impl<'tcx> Cx<'tcx> { | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { - self.typeck_results().user_provided_types().get(hir_id).copied().map(Box::new) + self.typeck_results.user_provided_types().get(hir_id).copied().map(Box::new) } // A unit struct/variant which is used as a value (e.g., @@ -989,17 +985,13 @@ impl<'tcx> Cx<'tcx> { Some(fn_def) => (fn_def, None), None => { let (kind, def_id) = - self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| { + self.typeck_results.type_dependent_def(expr.hir_id).unwrap_or_else(|| { span_bug!(expr.span, "no type-dependent def for method callee") }); let user_ty = self.user_args_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); debug!("method_callee: user_ty={:?}", user_ty); ( - Ty::new_fn_def( - self.tcx(), - def_id, - self.typeck_results().node_args(expr.hir_id), - ), + Ty::new_fn_def(self.tcx, def_id, self.typeck_results.node_args(expr.hir_id)), user_ty, ) } @@ -1025,7 +1017,7 @@ impl<'tcx> Cx<'tcx> { } fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { - let args = self.typeck_results().node_args(expr.hir_id); + let args = self.typeck_results.node_args(expr.hir_id); match res { // A regular function, constructor function or a constant. Res::Def(DefKind::Fn, _) @@ -1060,7 +1052,7 @@ impl<'tcx> Cx<'tcx> { let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new); debug!("convert_path_expr: user_ty={:?}", user_ty); - let ty = self.typeck_results().node_type(expr.hir_id); + let ty = self.typeck_results.node_type(expr.hir_id); match ty.kind() { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index a98c2bb61f66..823f2820f40d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -16,7 +16,6 @@ use rustc_middle::ty::{self, RvalueScopes, TyCtxt}; use tracing::instrument; use crate::thir::pattern::pat_from_hir; -use crate::thir::util::UserAnnotatedTyHelpers; pub(crate) fn thir_body( tcx: TyCtxt<'_>, @@ -113,7 +112,7 @@ impl<'tcx> Cx<'tcx> { #[instrument(level = "debug", skip(self))] fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { - pat_from_hir(self.tcx, self.typing_env, self.typeck_results(), p) + pat_from_hir(self.tcx, self.typing_env, self.typeck_results, p) } fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option> { @@ -197,15 +196,12 @@ impl<'tcx> Cx<'tcx> { Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) } }) } -} -impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn typeck_results(&self) -> &ty::TypeckResults<'tcx> { - self.typeck_results + fn user_args_applied_to_ty_of_hir_id( + &self, + hir_id: HirId, + ) -> Option> { + crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 20a728d6d5b2..b297afcb4d04 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -27,7 +27,6 @@ use tracing::{debug, instrument}; pub(crate) use self::check_match::check_match; use crate::errors::*; use crate::fluent_generated as fluent; -use crate::thir::util::UserAnnotatedTyHelpers; struct PatCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -537,16 +536,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => { let e = match res { Res::Def(DefKind::ConstParam, def_id) => { - self.tcx.dcx().emit_err(ConstParamInPattern { - span, - const_span: self.tcx().def_span(def_id), - }) + let const_span = self.tcx.def_span(def_id); + self.tcx.dcx().emit_err(ConstParamInPattern { span, const_span }) } Res::Def(DefKind::Static { .. }, def_id) => { - self.tcx.dcx().emit_err(StaticInPattern { - span, - static_span: self.tcx().def_span(def_id), - }) + let static_span = self.tcx.def_span(def_id); + self.tcx.dcx().emit_err(StaticInPattern { span, static_span }) } _ => self.tcx.dcx().emit_err(NonConstPath { span }), }; @@ -570,6 +565,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { kind } + fn user_args_applied_to_ty_of_hir_id( + &self, + hir_id: hir::HirId, + ) -> Option> { + crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id) + } + /// Takes a HIR Path. If the path is a constant, evaluates it and feeds /// it to `const_to_pat`. Any other path (like enum variants without fields) /// is converted to the corresponding pattern via `lower_variant_or_leaf`. @@ -600,12 +602,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return pattern; } - let user_provided_types = self.typeck_results().user_provided_types(); + let user_provided_types = self.typeck_results.user_provided_types(); if let Some(&user_ty) = user_provided_types.get(id) { let annotation = CanonicalUserTypeAnnotation { user_ty: Box::new(user_ty), span, - inferred_ty: self.typeck_results().node_type(id), + inferred_ty: self.typeck_results.node_type(id), }; Box::new(Pat { span, @@ -669,13 +671,3 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind } } - -impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - fn typeck_results(&self) -> &ty::TypeckResults<'tcx> { - self.typeck_results - } -} diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index ed7c7e409930..4dff093afd0d 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -1,33 +1,27 @@ use rustc_hir as hir; use rustc_middle::bug; -use rustc_middle::ty::{self, CanonicalUserType, TyCtxt}; +use rustc_middle::ty::{self, CanonicalUserType}; use tracing::debug; -pub(crate) trait UserAnnotatedTyHelpers<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx>; - - fn typeck_results(&self) -> &ty::TypeckResults<'tcx>; - - /// Looks up the type associated with this hir-id and applies the - /// user-given generic parameters; the hir-id must map to a suitable - /// type. - fn user_args_applied_to_ty_of_hir_id( - &self, - hir_id: hir::HirId, - ) -> Option> { - let user_provided_types = self.typeck_results().user_provided_types(); - let mut user_ty = *user_provided_types.get(hir_id)?; - debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); - let ty = self.typeck_results().node_type(hir_id); - match ty.kind() { - ty::Adt(adt_def, ..) => { - if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind { - *did = adt_def.did(); - } - Some(user_ty) +/// Looks up the type associated with this hir-id and applies the +/// user-given generic parameters; the hir-id must map to a suitable +/// type. +pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>( + typeck_results: &ty::TypeckResults<'tcx>, + hir_id: hir::HirId, +) -> Option> { + let user_provided_types = typeck_results.user_provided_types(); + let mut user_ty = *user_provided_types.get(hir_id)?; + debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); + let ty = typeck_results.node_type(hir_id); + match ty.kind() { + ty::Adt(adt_def, ..) => { + if let ty::UserTypeKind::TypeOf(ref mut did, _) = &mut user_ty.value.kind { + *did = adt_def.did(); } - ty::FnDef(..) => Some(user_ty), - _ => bug!("ty: {:?} should not have user provided type {:?} recorded ", ty, user_ty), + Some(user_ty) } + ty::FnDef(..) => Some(user_ty), + _ => bug!("ty: {:?} should not have user provided type {:?} recorded ", ty, user_ty), } } From abd900259da5b8b051c4b5a4526c722fb1295d26 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 4 Feb 2025 15:43:02 +1100 Subject: [PATCH 63/68] Rename `thir::cx::Cx` to `ThirBuildCx` --- compiler/rustc_mir_build/src/thir/cx/block.rs | 4 ++-- compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 ++-- compiler/rustc_mir_build/src/thir/cx/mod.rs | 13 ++++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index c9df027687ab..e858b629ab14 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -6,9 +6,9 @@ use rustc_middle::ty; use rustc_middle::ty::CanonicalUserTypeAnnotation; use tracing::debug; -use crate::thir::cx::Cx; +use crate::thir::cx::ThirBuildCx; -impl<'tcx> Cx<'tcx> { +impl<'tcx> ThirBuildCx<'tcx> { pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 8eec0fe12d41..54da6924db44 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -21,9 +21,9 @@ use rustc_middle::{bug, span_bug}; use rustc_span::{Span, sym}; use tracing::{debug, info, instrument, trace}; -use crate::thir::cx::Cx; +use crate::thir::cx::ThirBuildCx; -impl<'tcx> Cx<'tcx> { +impl<'tcx> ThirBuildCx<'tcx> { /// Create a THIR expression for the given HIR expression. This expands all /// adjustments and directly adds the type information from the /// `typeck_results`. See the [dev-guide] for more details. diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 823f2820f40d..9d114e675593 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -17,13 +17,14 @@ use tracing::instrument; use crate::thir::pattern::pat_from_hir; +/// Query implementation for [`TyCtxt::thir_body`]. pub(crate) fn thir_body( tcx: TyCtxt<'_>, owner_def: LocalDefId, ) -> Result<(&Steal>, ExprId), ErrorGuaranteed> { let hir = tcx.hir(); let body = hir.body_owned_by(owner_def); - let mut cx = Cx::new(tcx, owner_def); + let mut cx = ThirBuildCx::new(tcx, owner_def); if let Some(reported) = cx.typeck_results.tainted_by_errors { return Err(reported); } @@ -51,8 +52,10 @@ pub(crate) fn thir_body( Ok((tcx.alloc_steal_thir(cx.thir), expr)) } -struct Cx<'tcx> { +/// Context for lowering HIR to THIR for a single function body (or other kind of body). +struct ThirBuildCx<'tcx> { tcx: TyCtxt<'tcx>, + /// The THIR data that this context is building. thir: Thir<'tcx>, typing_env: ty::TypingEnv<'tcx>, @@ -68,8 +71,8 @@ struct Cx<'tcx> { body_owner: DefId, } -impl<'tcx> Cx<'tcx> { - fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Cx<'tcx> { +impl<'tcx> ThirBuildCx<'tcx> { + fn new(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self { let typeck_results = tcx.typeck(def); let hir = tcx.hir(); let hir_id = tcx.local_def_id_to_hir_id(def); @@ -93,7 +96,7 @@ impl<'tcx> Cx<'tcx> { BodyTy::Const(typeck_results.node_type(hir_id)) }; - Cx { + Self { tcx, thir: Thir::new(body_type), // FIXME(#132279): We're in a body, we should use a typing From cb028dc3b7c549b6becd6da821b2bcb9339a1a21 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 1 Feb 2025 19:46:21 +0000 Subject: [PATCH 64/68] librustdoc: create a helper for separating elements of an iterator instead of implementing it multiple times --- src/librustdoc/clean/cfg.rs | 59 +++-- src/librustdoc/html/format.rs | 262 +++++++++-------------- src/librustdoc/html/render/print_item.rs | 58 +++-- src/librustdoc/joined.rs | 29 +++ src/librustdoc/lib.rs | 1 + 5 files changed, 203 insertions(+), 206 deletions(-) create mode 100644 src/librustdoc/joined.rs diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index bdd44b4a9932..b576f28176e5 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -14,6 +14,7 @@ use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; use crate::html::escape::Escape; +use crate::joined::Joined as _; #[cfg(test)] mod tests; @@ -396,6 +397,8 @@ impl Display<'_> { sub_cfgs: &[Cfg], separator: &str, ) -> fmt::Result { + use fmt::Display as _; + let short_longhand = self.1.is_long() && { let all_crate_features = sub_cfgs.iter().all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); @@ -414,20 +417,29 @@ impl Display<'_> { } }; - for (i, sub_cfg) in sub_cfgs.iter().enumerate() { - if i != 0 { - fmt.write_str(separator)?; - } - if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { - if self.1.is_html() { - write!(fmt, "{feat}")?; - } else { - write!(fmt, "`{feat}`")?; - } - } else { - write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; - } - } + fmt::from_fn(|f| { + sub_cfgs + .iter() + .map(|sub_cfg| { + fmt::from_fn(move |fmt| { + if let Cfg::Cfg(_, Some(feat)) = sub_cfg + && short_longhand + { + if self.1.is_html() { + write!(fmt, "{feat}")?; + } else { + write!(fmt, "`{feat}`")?; + } + } else { + write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; + } + Ok(()) + }) + }) + .joined(separator, f) + }) + .fmt(fmt)?; + Ok(()) } } @@ -439,11 +451,20 @@ impl fmt::Display for Display<'_> { Cfg::Any(ref sub_cfgs) => { let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " }; - for (i, sub_cfg) in sub_cfgs.iter().enumerate() { - fmt.write_str(if i == 0 { "neither " } else { separator })?; - write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; - } - Ok(()) + fmt.write_str("neither ")?; + + sub_cfgs + .iter() + .map(|sub_cfg| { + fmt::from_fn(|fmt| { + write_with_opt_paren( + fmt, + !sub_cfg.is_all(), + Display(sub_cfg, self.1), + ) + }) + }) + .joined(separator, fmt) } ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Display(simple, self.1)), ref c => write!(fmt, "not ({})", Display(c, self.1)), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index ffd457c82737..b6a73602a322 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -8,12 +8,11 @@ //! not be used external to this module. use std::borrow::Cow; -use std::cell::Cell; use std::cmp::Ordering; use std::fmt::{self, Display, Write}; use std::iter::{self, once}; -use itertools::Itertools; +use itertools::Either; use rustc_abi::ExternAbi; use rustc_attr_parsing::{ConstStability, StabilityLevel, StableSince}; use rustc_data_structures::captures::Captures; @@ -35,6 +34,7 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyText}; use crate::html::render::Context; +use crate::joined::Joined as _; use crate::passes::collect_intra_doc_links::UrlFragment; pub(crate) trait Print { @@ -146,22 +146,6 @@ impl Buffer { } } -pub(crate) fn comma_sep( - items: impl Iterator, - space_after_comma: bool, -) -> impl Display { - let items = Cell::new(Some(items)); - fmt::from_fn(move |f| { - for (i, item) in items.take().unwrap().enumerate() { - if i != 0 { - write!(f, ",{}", if space_after_comma { " " } else { "" })?; - } - item.fmt(f)?; - } - Ok(()) - }) -} - pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>( bounds: &'a [clean::GenericBound], cx: &'a Context<'tcx>, @@ -169,13 +153,11 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>( fmt::from_fn(move |f| { let mut bounds_dup = FxHashSet::default(); - for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(*b)).enumerate() { - if i > 0 { - f.write_str(" + ")?; - } - bound.print(cx).fmt(f)?; - } - Ok(()) + bounds + .iter() + .filter(move |b| bounds_dup.insert(*b)) + .map(|bound| bound.print(cx)) + .joined(" + ", f) }) } @@ -190,12 +172,7 @@ impl clean::GenericParamDef { if !outlives.is_empty() { f.write_str(": ")?; - for (i, lt) in outlives.iter().enumerate() { - if i != 0 { - f.write_str(" + ")?; - } - write!(f, "{}", lt.print())?; - } + outlives.iter().map(|lt| lt.print()).joined(" + ", f)?; } Ok(()) @@ -245,10 +222,12 @@ impl clean::Generics { return Ok(()); } + let real_params = + fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f)); if f.alternate() { - write!(f, "<{:#}>", comma_sep(real_params.map(|g| g.print(cx)), true)) + write!(f, "<{:#}>", real_params) } else { - write!(f, "<{}>", comma_sep(real_params.map(|g| g.print(cx)), true)) + write!(f, "<{}>", real_params) } }) } @@ -260,6 +239,42 @@ pub(crate) enum Ending { NoNewline, } +fn print_where_predicate<'a, 'tcx: 'a>( + predicate: &'a clean::WherePredicate, + cx: &'a Context<'tcx>, +) -> impl Display + 'a + Captures<'tcx> { + fmt::from_fn(move |f| { + match predicate { + clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => { + print_higher_ranked_params_with_space(bound_params, cx, "for").fmt(f)?; + ty.print(cx).fmt(f)?; + f.write_str(":")?; + if !bounds.is_empty() { + f.write_str(" ")?; + print_generic_bounds(bounds, cx).fmt(f)?; + } + Ok(()) + } + clean::WherePredicate::RegionPredicate { lifetime, bounds } => { + // We don't need to check `alternate` since we can be certain that neither + // the lifetime nor the bounds contain any characters which need escaping. + write!(f, "{}:", lifetime.print())?; + if !bounds.is_empty() { + write!(f, " {}", print_generic_bounds(bounds, cx))?; + } + Ok(()) + } + clean::WherePredicate::EqPredicate { lhs, rhs } => { + if f.alternate() { + write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx)) + } else { + write!(f, "{} == {}", lhs.print(cx), rhs.print(cx)) + } + } + } + }) +} + /// * The Generics from which to emit a where-clause. /// * The number of spaces to indent each line with. /// * Whether the where-clause needs to add a comma and newline after the last bound. @@ -270,55 +285,26 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( ending: Ending, ) -> impl Display + 'a + Captures<'tcx> { fmt::from_fn(move |f| { - let mut where_predicates = gens - .where_predicates - .iter() - .map(|pred| { - fmt::from_fn(move |f| { - if f.alternate() { - f.write_str(" ")?; - } else { - f.write_str("\n")?; - } - - match pred { - clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => { - print_higher_ranked_params_with_space(bound_params, cx, "for") - .fmt(f)?; - ty.print(cx).fmt(f)?; - f.write_str(":")?; - if !bounds.is_empty() { - f.write_str(" ")?; - print_generic_bounds(bounds, cx).fmt(f)?; - } - Ok(()) - } - clean::WherePredicate::RegionPredicate { lifetime, bounds } => { - // We don't need to check `alternate` since we can be certain that neither - // the lifetime nor the bounds contain any characters which need escaping. - write!(f, "{}:", lifetime.print())?; - if !bounds.is_empty() { - write!(f, " {}", print_generic_bounds(bounds, cx))?; - } - Ok(()) - } - clean::WherePredicate::EqPredicate { lhs, rhs } => { - if f.alternate() { - write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx)) - } else { - write!(f, "{} == {}", lhs.print(cx), rhs.print(cx)) - } - } - } - }) - }) - .peekable(); - - if where_predicates.peek().is_none() { + if gens.where_predicates.is_empty() { return Ok(()); } - let where_preds = comma_sep(where_predicates, false); + let where_preds = fmt::from_fn(|f| { + gens.where_predicates + .iter() + .map(|predicate| { + fmt::from_fn(|f| { + if f.alternate() { + f.write_str(" ")?; + } else { + f.write_str("\n")?; + } + print_where_predicate(predicate, cx).fmt(f) + }) + }) + .joined(",", f) + }); + let clause = if f.alternate() { if ending == Ending::Newline { format!(" where{where_preds},") @@ -415,12 +401,7 @@ impl clean::GenericBound { } else { f.write_str("use<")?; } - for (i, arg) in args.iter().enumerate() { - if i > 0 { - write!(f, ", ")?; - } - arg.fmt(f)?; - } + args.iter().joined(", ", f)?; if f.alternate() { f.write_str(">") } else { f.write_str(">") } } }) @@ -438,29 +419,18 @@ impl clean::GenericArgs { } else { f.write_str("<")?; } - let mut comma = false; - for arg in args.iter() { - if comma { - f.write_str(", ")?; - } - comma = true; - if f.alternate() { - write!(f, "{:#}", arg.print(cx))?; - } else { - write!(f, "{}", arg.print(cx))?; - } - } - for constraint in constraints.iter() { - if comma { - f.write_str(", ")?; - } - comma = true; - if f.alternate() { - write!(f, "{:#}", constraint.print(cx))?; - } else { - write!(f, "{}", constraint.print(cx))?; - } - } + + [Either::Left(args), Either::Right(constraints)] + .into_iter() + .flat_map(Either::factor_into_iter) + .map(|either| { + either.map_either( + |arg| arg.print(cx), + |constraint| constraint.print(cx), + ) + }) + .joined(", ", f)?; + if f.alternate() { f.write_str(">")?; } else { @@ -470,14 +440,7 @@ impl clean::GenericArgs { } clean::GenericArgs::Parenthesized { inputs, output } => { f.write_str("(")?; - let mut comma = false; - for ty in inputs.iter() { - if comma { - f.write_str(", ")?; - } - comma = true; - ty.print(cx).fmt(f)?; - } + inputs.iter().map(|ty| ty.print(cx)).joined(", ", f)?; f.write_str(")")?; if let Some(ref ty) = *output { if f.alternate() { @@ -524,6 +487,7 @@ pub(crate) enum HrefError { // Panics if `syms` is empty. pub(crate) fn join_with_double_colon(syms: &[Symbol]) -> String { let mut s = String::with_capacity(estimate_item_path_byte_length(syms.len())); + // NOTE: using `Joined::joined` here causes a noticeable perf regression s.push_str(syms[0].as_str()); for sym in &syms[1..] { s.push_str("::"); @@ -572,20 +536,20 @@ fn generate_macro_def_id_path( } if let Some(last) = path.last_mut() { - *last = Symbol::intern(&format!("macro.{}.html", last.as_str())); + *last = Symbol::intern(&format!("macro.{last}.html")); } let url = match cache.extern_locations[&def_id.krate] { ExternalLocation::Remote(ref s) => { // `ExternalLocation::Remote` always end with a `/`. - format!("{s}{path}", path = path.iter().map(|p| p.as_str()).join("/")) + format!("{s}{path}", path = fmt::from_fn(|f| path.iter().joined("/", f))) } ExternalLocation::Local => { // `root_path` always end with a `/`. format!( "{root_path}{path}", root_path = root_path.unwrap_or(""), - path = path.iter().map(|p| p.as_str()).join("/") + path = fmt::from_fn(|f| path.iter().joined("/", f)) ) } ExternalLocation::Unknown => { @@ -682,9 +646,8 @@ fn make_href( url_parts.push("index.html"); } _ => { - let prefix = shortty.as_str(); let last = fqp.last().unwrap(); - url_parts.push_fmt(format_args!("{prefix}.{last}.html")); + url_parts.push_fmt(format_args!("{shortty}.{last}.html")); } } Ok((url_parts.finish(), shortty, fqp.to_vec())) @@ -950,12 +913,7 @@ fn tybounds<'a, 'tcx: 'a>( cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { fmt::from_fn(move |f| { - for (i, bound) in bounds.iter().enumerate() { - if i > 0 { - write!(f, " + ")?; - } - bound.print(cx).fmt(f)?; - } + bounds.iter().map(|bound| bound.print(cx)).joined(" + ", f)?; if let Some(lt) = lt { // We don't need to check `alternate` since we can be certain that // the lifetime doesn't contain any characters which need escaping. @@ -974,7 +932,7 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>( if !params.is_empty() { f.write_str(keyword)?; f.write_str(if f.alternate() { "<" } else { "<" })?; - comma_sep(params.iter().map(|lt| lt.print(cx)), true).fmt(f)?; + params.iter().map(|lt| lt.print(cx)).joined(", ", f)?; f.write_str(if f.alternate() { "> " } else { "> " })?; } Ok(()) @@ -1025,9 +983,7 @@ fn fmt_type( clean::Primitive(clean::PrimitiveType::Never) => { primitive_link(f, PrimitiveType::Never, format_args!("!"), cx) } - clean::Primitive(prim) => { - primitive_link(f, prim, format_args!("{}", prim.as_sym().as_str()), cx) - } + clean::Primitive(prim) => primitive_link(f, prim, format_args!("{}", prim.as_sym()), cx), clean::BareFunction(ref decl) => { print_higher_ranked_params_with_space(&decl.generic_params, cx, "for").fmt(f)?; decl.safety.print_with_space().fmt(f)?; @@ -1067,18 +1023,16 @@ fn fmt_type( primitive_link( f, PrimitiveType::Tuple, - format_args!("({})", generic_names.iter().map(|s| s.as_str()).join(", ")), + format_args!( + "({})", + fmt::from_fn(|f| generic_names.iter().joined(", ", f)) + ), cx, ) } else { - write!(f, "(")?; - for (i, item) in many.iter().enumerate() { - if i != 0 { - write!(f, ", ")?; - } - item.print(cx).fmt(f)?; - } - write!(f, ")") + f.write_str("(")?; + many.iter().map(|item| item.print(cx)).joined(", ", f)?; + f.write_str(")") } } }, @@ -1407,16 +1361,17 @@ impl clean::Arguments { cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { fmt::from_fn(move |f| { - for (i, input) in self.values.iter().enumerate() { - if !input.name.is_empty() { - write!(f, "{}: ", input.name)?; - } - input.type_.print(cx).fmt(f)?; - if i + 1 < self.values.len() { - write!(f, ", ")?; - } - } - Ok(()) + self.values + .iter() + .map(|input| { + fmt::from_fn(|f| { + if !input.name.is_empty() { + write!(f, "{}: ", input.name)?; + } + input.type_.print(cx).fmt(f) + }) + }) + .joined(", ", f) }) } } @@ -1725,12 +1680,7 @@ impl clean::ImportSource { } let name = self.path.last(); if let hir::def::Res::PrimTy(p) = self.path.res { - primitive_link( - f, - PrimitiveType::from(p), - format_args!("{}", name.as_str()), - cx, - )?; + primitive_link(f, PrimitiveType::from(p), format_args!("{name}"), cx)?; } else { f.write_str(name.as_str())?; } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 37fea09ace31..3f2e1f05c4a3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; use std::fmt; +use std::fmt::{Display, Write}; use itertools::Itertools; use rinja::Template; @@ -36,6 +37,7 @@ use crate::html::format::{ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::{document_full, document_item_info}; use crate::html::url_parts_builder::UrlPartsBuilder; +use crate::joined::Joined as _; /// Generates a Rinja template struct for rendering items with common methods. /// @@ -290,7 +292,7 @@ fn should_hide_fields(n_fields: usize) -> bool { n_fields > 12 } -fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) { +fn toggle_open(mut w: impl fmt::Write, text: impl Display) { write!( w, "
\ @@ -305,7 +307,7 @@ fn toggle_close(mut w: impl fmt::Write) { w.write_str("
").unwrap(); } -trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display { +trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + Display { fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>); } @@ -519,13 +521,9 @@ fn extra_info_tags<'a, 'tcx: 'a>( item: &'a clean::Item, parent: &'a clean::Item, import_def_id: Option, -) -> impl fmt::Display + 'a + Captures<'tcx> { +) -> impl Display + 'a + Captures<'tcx> { fmt::from_fn(move |f| { - fn tag_html<'a>( - class: &'a str, - title: &'a str, - contents: &'a str, - ) -> impl fmt::Display + 'a { + fn tag_html<'a>(class: &'a str, title: &'a str, contents: &'a str) -> impl Display + 'a { fmt::from_fn(move |f| { write!( f, @@ -1374,7 +1372,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni ); impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { - fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + fn render_union<'b>(&'b self) -> impl Display + Captures<'a> + 'b + Captures<'cx> { fmt::from_fn(move |f| { let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx); write!(f, "{v}") @@ -1384,7 +1382,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni fn document_field<'b>( &'b self, field: &'a clean::Item, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + ) -> impl Display + Captures<'a> + 'b + Captures<'cx> { fmt::from_fn(move |f| { let v = document(self.cx, field, Some(self.it), HeadingOffset::H3); write!(f, "{v}") @@ -1398,7 +1396,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni fn print_ty<'b>( &'b self, ty: &'a clean::Type, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + ) -> impl Display + Captures<'a> + 'b + Captures<'cx> { fmt::from_fn(move |f| { let v = ty.print(self.cx); write!(f, "{v}") @@ -1425,7 +1423,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni fn print_tuple_struct_fields<'a, 'cx: 'a>( cx: &'a Context<'cx>, s: &'a [clean::Item], -) -> impl fmt::Display + 'a + Captures<'cx> { +) -> impl Display + 'a + Captures<'cx> { fmt::from_fn(|f| { if !s.is_empty() && s.iter().all(|field| { @@ -1435,17 +1433,15 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( return f.write_str("/* private fields */"); } - for (i, ty) in s.iter().enumerate() { - if i > 0 { - f.write_str(", ")?; - } - match ty.kind { - clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?, - clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?, - _ => unreachable!(), - } - } - Ok(()) + s.iter() + .map(|ty| { + fmt::from_fn(|f| match ty.kind { + clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_"), + clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx)), + _ => unreachable!(), + }) + }) + .joined(", ", f) }) } @@ -2068,12 +2064,12 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) bounds.push_str(": "); } } - for (i, p) in t_bounds.iter().enumerate() { - if i > 0 { - bounds.push_str(inter_str); - } - bounds.push_str(&p.print(cx).to_string()); - } + write!( + bounds, + "{}", + fmt::from_fn(|f| t_bounds.iter().map(|p| p.print(cx)).joined(inter_str, f)) + ) + .unwrap(); bounds } @@ -2150,7 +2146,7 @@ fn render_union<'a, 'cx: 'a>( g: Option<&'a clean::Generics>, fields: &'a [clean::Item], cx: &'a Context<'cx>, -) -> impl fmt::Display + 'a + Captures<'cx> { +) -> impl Display + 'a + Captures<'cx> { fmt::from_fn(move |mut f| { write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?; @@ -2330,7 +2326,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" } } -fn document_non_exhaustive(item: &clean::Item) -> impl fmt::Display + '_ { +fn document_non_exhaustive(item: &clean::Item) -> impl Display + '_ { fmt::from_fn(|f| { if item.is_non_exhaustive() { write!( diff --git a/src/librustdoc/joined.rs b/src/librustdoc/joined.rs new file mode 100644 index 000000000000..f369c6cf2371 --- /dev/null +++ b/src/librustdoc/joined.rs @@ -0,0 +1,29 @@ +use std::fmt::{self, Display, Formatter}; + +pub(crate) trait Joined: IntoIterator { + /// Takes an iterator over elements that implement [`Display`], and format them into `f`, separated by `sep`. + /// + /// This is similar to [`Itertools::format`](itertools::Itertools::format), but instead of returning an implementation of `Display`, + /// it formats directly into a [`Formatter`]. + /// + /// The performance of `joined` is slightly better than `format`, since it doesn't need to use a `Cell` to keep track of whether [`fmt`](Display::fmt) + /// was already called (`joined`'s API doesn't allow it be called more than once). + fn joined(self, sep: &str, f: &mut Formatter<'_>) -> fmt::Result; +} + +impl Joined for I +where + I: IntoIterator, + T: Display, +{ + fn joined(self, sep: &str, f: &mut Formatter<'_>) -> fmt::Result { + let mut iter = self.into_iter(); + let Some(first) = iter.next() else { return Ok(()) }; + first.fmt(f)?; + while let Some(item) = iter.next() { + f.write_str(sep)?; + item.fmt(f)?; + } + Ok(()) + } +} diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index af225c9d68dd..98c4a60bd89a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -113,6 +113,7 @@ mod fold; mod formats; // used by the error-index generator, so it needs to be public pub mod html; +mod joined; mod json; pub(crate) mod lint; mod markdown; From b1b388e98a361b2a3b5c122cb8811ee4503575c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Feb 2025 10:42:50 +0000 Subject: [PATCH 65/68] fix NLL TLS end of function spans --- .../src/diagnostics/conflict_errors.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index dc4e49972ca0..b3fb2cd938b6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3112,12 +3112,24 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { drop_span, borrow_span ); + // `TerminatorKind::Return`'s span (the `drop_span` here) `lo` can be subtly wrong and point + // at a single character after the end of the function. This is somehow relied upon in + // existing diagnostics, and changing this in `rustc_mir_build` makes diagnostics worse in + // general. We fix these here. + let sm = self.infcx.tcx.sess.source_map(); + let end_of_function = if drop_span.is_empty() + && let Ok(adjusted_span) = sm.span_extend_prev_while(drop_span, |c| c == '}') + { + adjusted_span + } else { + drop_span + }; self.thread_local_value_does_not_live_long_enough(borrow_span) .with_span_label( borrow_span, "thread-local variables cannot be borrowed beyond the end of the function", ) - .with_span_label(drop_span, "end of enclosing function is here") + .with_span_label(end_of_function, "end of enclosing function is here") } #[instrument(level = "debug", skip(self))] From d2a30f7d884fecfea60ed540aa830a75013e43b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Mon, 3 Feb 2025 10:43:27 +0000 Subject: [PATCH 66/68] bless test expectations --- .../borrowck-thread-local-static-borrow-outlives-fn.stderr | 2 +- tests/ui/issues/issue-17954.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr index 11ee8f7bb91a..6e0c69a4eb07 100644 --- a/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr +++ b/tests/ui/borrowck/borrowck-thread-local-static-borrow-outlives-fn.stderr @@ -4,7 +4,7 @@ error[E0712]: thread-local variable borrowed past end of function LL | assert_static(&FOO); | ^^^^ thread-local variables cannot be borrowed beyond the end of the function LL | } - | - end of enclosing function is here + | - end of enclosing function is here error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-17954.stderr b/tests/ui/issues/issue-17954.stderr index bba7e725b124..0dddea833648 100644 --- a/tests/ui/issues/issue-17954.stderr +++ b/tests/ui/issues/issue-17954.stderr @@ -5,7 +5,7 @@ LL | let a = &FOO; | ^^^^ thread-local variables cannot be borrowed beyond the end of the function ... LL | } - | - end of enclosing function is here + | - end of enclosing function is here error: aborting due to 1 previous error From fbcaa9b0a16cb3eed67cc3dc2429574f28dcac17 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Jan 2025 16:39:30 +0000 Subject: [PATCH 67/68] Allow using named consts in pattern types --- compiler/rustc_ast_lowering/src/pat.rs | 27 +++---- .../src/collect/generics_of.rs | 1 + .../pattern_types/assoc_const.default.stderr | 36 ++++++++++ tests/ui/type/pattern_types/assoc_const.rs | 24 +++++++ .../bad_const_generics_args_on_const_param.rs | 11 +-- ..._const_generics_args_on_const_param.stderr | 48 +++---------- tests/ui/type/pattern_types/const_block.rs | 10 +++ .../ui/type/pattern_types/const_block.stderr | 72 +++++++++++++++++++ tests/ui/type/pattern_types/free_const.rs | 13 ++++ 9 files changed, 186 insertions(+), 56 deletions(-) create mode 100644 tests/ui/type/pattern_types/assoc_const.default.stderr create mode 100644 tests/ui/type/pattern_types/assoc_const.rs create mode 100644 tests/ui/type/pattern_types/const_block.rs create mode 100644 tests/ui/type/pattern_types/const_block.stderr create mode 100644 tests/ui/type/pattern_types/free_const.rs diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 57f15f99760a..bb9b2a13185b 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -440,17 +440,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let node = loop { match &pattern.kind { PatKind::Range(e1, e2, Spanned { node: end, .. }) => { + // FIXME(pattern_types): remove this closure and call `lower_const_arg` instead. + // That requires first modifying the AST to have const args here. let mut lower_expr = |e: &Expr| -> &_ { - let kind = if let ExprKind::Path(qself, path) = &e.kind { - hir::ConstArgKind::Path(self.lower_qpath( - e.id, - qself, - path, - ParamMode::Optional, - AllowReturnTypeNotation::No, - ImplTraitContext::Disallowed(ImplTraitPosition::Path), - None, - )) + if let ExprKind::Path(None, path) = &e.kind + && let Some(res) = self + .resolver + .get_partial_res(e.id) + .and_then(|partial_res| partial_res.full_res()) + { + self.lower_const_path_to_const_arg(path, res, e.id, e.span) } else { let node_id = self.next_node_id(); let def_id = self.create_def( @@ -467,9 +466,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { body: self.lower_const_body(pattern.span, Some(e)), span: self.lower_span(pattern.span), }); - hir::ConstArgKind::Anon(ac) - }; - self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind }) + self.arena.alloc(hir::ConstArg { + hir_id: self.next_id(), + kind: hir::ConstArgKind::Anon(ac), + }) + } }; break hir::TyPatKind::Range( e1.as_deref().map(|e| lower_expr(e)), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 2ac8acbd3a4b..c0902398a54a 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -198,6 +198,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { { Some(parent_did) } + Node::TyPat(_) => Some(parent_did), _ => None, } } diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr new file mode 100644 index 000000000000..abda40e46816 --- /dev/null +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -0,0 +1,36 @@ +error: constant expression depends on a generic parameter + --> $DIR/assoc_const.rs:17:19 + | +LL | fn foo(_: pattern_type!(u32 is ::START..=::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/assoc_const.rs:17:19 + | +LL | fn foo(_: pattern_type!(u32 is ::START..=::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: constant expression depends on a generic parameter + --> $DIR/assoc_const.rs:20:19 + | +LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: constant expression depends on a generic parameter + --> $DIR/assoc_const.rs:20:19 + | +LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs new file mode 100644 index 000000000000..af0f7e4cbf32 --- /dev/null +++ b/tests/ui/type/pattern_types/assoc_const.rs @@ -0,0 +1,24 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] +#![cfg_attr(const_arg, feature(generic_const_exprs))] +#![expect(incomplete_features)] + +//@ revisions: default const_arg + +//@[const_arg] check-pass + +use std::pat::pattern_type; + +trait Foo { + const START: u32; + const END: u32; +} + +fn foo(_: pattern_type!(u32 is ::START..=::END)) {} +//[default]~^ ERROR: constant expression depends on a generic parameter +//[default]~| ERROR: constant expression depends on a generic parameter +fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} +//[default]~^ ERROR: constant expression depends on a generic parameter +//[default]~| ERROR: constant expression depends on a generic parameter + +fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 05e308de7b1e..0f10bf8ce627 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -1,11 +1,14 @@ +//@known-bug: #127972 +//@ failure-status: 101 +//@ normalize-stderr: "note: .*\n\n" -> "" +//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> "" +//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@ rustc-env:RUST_BACKTRACE=0 + #![feature(pattern_types, pattern_type_macro)] #![allow(internal_features)] type Pat = std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); -//~^ ERROR type and const arguments are not allowed on const parameter `START` -//~| ERROR generic arguments are not allowed on const parameter `END` -//~| ERROR associated item constraints are not allowed here -//~| ERROR `_` is not allowed within types on item signatures for type aliases fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index c4ba89de3f36..fbe80a19863d 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -1,44 +1,14 @@ -error[E0109]: type and const arguments are not allowed on const parameter `START` - --> $DIR/bad_const_generics_args_on_const_param.rs:5:44 +error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible + --> $DIR/bad_const_generics_args_on_const_param.rs:12:36 | LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | ----- ^^ ^^^ ^ type and const arguments not allowed - | | - | not allowed on const parameter `START` - | -note: const parameter `START` defined here - --> $DIR/bad_const_generics_args_on_const_param.rs:4:16 - | -LL | type Pat = - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^ -error[E0109]: generic arguments are not allowed on const parameter `END` - --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 - | -LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | --- ^ generic argument not allowed - | | - | not allowed on const parameter `END` - | -note: const parameter `END` defined here - --> $DIR/bad_const_generics_args_on_const_param.rs:4:34 - | -LL | type Pat = - | ^^^ -error[E0229]: associated item constraints are not allowed here - --> $DIR/bad_const_generics_args_on_const_param.rs:5:67 - | -LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | ^^^^^^^^^^ associated item constraint not allowed here +Box +query stack during panic: +#0 [type_of] expanding type alias `Pat` +#1 [check_well_formed] checking that `Pat` is well-formed +... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack +error: aborting due to 1 previous error -error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases - --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 - | -LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | ^ not allowed in type signatures - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0109, E0121, E0229. -For more information about an error, try `rustc --explain E0109`. diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs new file mode 100644 index 000000000000..49c87f4fa0d6 --- /dev/null +++ b/tests/ui/type/pattern_types/const_block.rs @@ -0,0 +1,10 @@ +#![feature(pattern_types)] +#![feature(pattern_type_macro)] +#![feature(inline_const_pat)] + +use std::pat::pattern_type; + +fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} +//~^ ERROR: cycle + +fn main() {} diff --git a/tests/ui/type/pattern_types/const_block.stderr b/tests/ui/type/pattern_types/const_block.stderr new file mode 100644 index 000000000000..82b616105afa --- /dev/null +++ b/tests/ui/type/pattern_types/const_block.stderr @@ -0,0 +1,72 @@ +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/const_block.rs:7:36 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `bar::{constant#2}`... + --> $DIR/const_block.rs:7:36 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `bar::{constant#2}` for CTFE... + --> $DIR/const_block.rs:7:36 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `bar::{constant#2}`... + --> $DIR/const_block.rs:7:36 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `bar::{constant#2}`... + --> $DIR/const_block.rs:7:36 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires promoting constants in MIR for `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires const checking `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires building MIR for `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires match-checking `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires type-checking `bar::{constant#0}`... + --> $DIR/const_block.rs:7:41 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^ +note: ...which requires type-checking `bar`... + --> $DIR/const_block.rs:7:1 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires evaluating type-level constant, completing the cycle +note: cycle used when checking that `bar` is well-formed + --> $DIR/const_block.rs:7:1 + | +LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/type/pattern_types/free_const.rs b/tests/ui/type/pattern_types/free_const.rs new file mode 100644 index 000000000000..2e29fce23797 --- /dev/null +++ b/tests/ui/type/pattern_types/free_const.rs @@ -0,0 +1,13 @@ +//@ check-pass + +#![feature(pattern_types)] +#![feature(pattern_type_macro)] + +use std::pat::pattern_type; + +const START: u32 = 0; +const END: u32 = 10; + +fn foo(_: pattern_type!(u32 is START..=END)) {} + +fn main() {} From fab6d8ae8c14cf3b4a53b7a716ce4809be35ffaf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Feb 2025 11:45:50 +0000 Subject: [PATCH 68/68] Prevent generic pattern types from being used in libstd --- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_span/src/symbol.rs | 1 + .../rustc_trait_selection/src/traits/wf.rs | 44 ++++++++++++++++- .../pattern_types/assoc_const.default.stderr | 49 +++++++++++++++++-- tests/ui/type/pattern_types/assoc_const.rs | 8 ++- tests/ui/type/pattern_types/const_generics.rs | 4 +- tests/ui/type/pattern_types/transmute.rs | 4 +- 7 files changed, 101 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 784063b0e31a..8aaa2d443925 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -507,6 +507,8 @@ declare_features! ( (incomplete, generic_const_exprs, "1.56.0", Some(76560)), /// Allows generic parameters and where-clauses on free & associated const items. (incomplete, generic_const_items, "1.73.0", Some(113521)), + /// Allows any generic constants being used as pattern type range ends + (incomplete, generic_pattern_types, "CURRENT_RUSTC_VERSION", Some(136574)), /// Allows registering static items globally, possibly across crates, to iterate over at runtime. (unstable, global_registration, "1.80.0", Some(125119)), /// Allows using guards in patterns. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 75a472d896fc..621d150281ca 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1013,6 +1013,7 @@ symbols! { generic_const_exprs, generic_const_items, generic_param_attrs, + generic_pattern_types, get_context, global_alloc_ty, global_allocator, diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 96051ad0aa54..c27bd269b0d9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -8,8 +8,9 @@ use rustc_middle::ty::{ self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_span::Span; +use rustc_session::parse::feature_err; use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::{Span, sym}; use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; @@ -704,8 +705,47 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { )); } - ty::Pat(subty, _) => { + ty::Pat(subty, pat) => { self.require_sized(subty, ObligationCauseCode::Misc); + match *pat { + ty::PatternKind::Range { start, end, include_end: _ } => { + let mut check = |c| { + let cause = self.cause(ObligationCauseCode::Misc); + self.out.push(traits::Obligation::with_depth( + tcx, + cause.clone(), + self.recursion_depth, + self.param_env, + ty::Binder::dummy(ty::PredicateKind::Clause( + ty::ClauseKind::ConstArgHasType(c, subty), + )), + )); + if !tcx.features().generic_pattern_types() { + if c.has_param() { + if self.span.is_dummy() { + self.tcx().dcx().delayed_bug( + "feature error should be reported elsewhere, too", + ); + } else { + feature_err( + &self.tcx().sess, + sym::generic_pattern_types, + self.span, + "wraparound pattern type ranges cause monomorphization time errors", + ) + .emit(); + } + } + } + }; + if let Some(start) = start { + check(start) + } + if let Some(end) = end { + check(end) + } + } + } } ty::Tuple(tys) => { diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr index abda40e46816..c5d9691a0291 100644 --- a/tests/ui/type/pattern_types/assoc_const.default.stderr +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -1,3 +1,24 @@ +error[E0658]: wraparound pattern type ranges cause monomorphization time errors + --> $DIR/assoc_const.rs:17:19 + | +LL | fn foo(_: pattern_type!(u32 is ::START..=::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #136574 for more information + = help: add `#![feature(generic_pattern_types)]` 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[E0658]: wraparound pattern type ranges cause monomorphization time errors + --> $DIR/assoc_const.rs:17:19 + | +LL | fn foo(_: pattern_type!(u32 is ::START..=::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #136574 for more information + = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: constant expression depends on a generic parameter --> $DIR/assoc_const.rs:17:19 | @@ -15,8 +36,29 @@ LL | fn foo(_: pattern_type!(u32 is ::START..=::END) = note: this may fail depending on what value the parameter takes = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +error[E0658]: wraparound pattern type ranges cause monomorphization time errors + --> $DIR/assoc_const.rs:22:19 + | +LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #136574 for more information + = help: add `#![feature(generic_pattern_types)]` 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[E0658]: wraparound pattern type ranges cause monomorphization time errors + --> $DIR/assoc_const.rs:22:19 + | +LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #136574 for more information + = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:20:19 + --> $DIR/assoc_const.rs:22:19 | LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,7 +66,7 @@ LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} = note: this may fail depending on what value the parameter takes error: constant expression depends on a generic parameter - --> $DIR/assoc_const.rs:20:19 + --> $DIR/assoc_const.rs:22:19 | LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,5 +74,6 @@ LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} = note: this may fail depending on what value the parameter takes = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 4 previous errors +error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs index af0f7e4cbf32..87886587d515 100644 --- a/tests/ui/type/pattern_types/assoc_const.rs +++ b/tests/ui/type/pattern_types/assoc_const.rs @@ -1,8 +1,8 @@ #![feature(pattern_types)] #![feature(pattern_type_macro)] -#![cfg_attr(const_arg, feature(generic_const_exprs))] +#![cfg_attr(const_arg, feature(generic_const_exprs, generic_pattern_types))] #![expect(incomplete_features)] - +// gate-test-generic_pattern_types line to the test file. //@ revisions: default const_arg //@[const_arg] check-pass @@ -17,8 +17,12 @@ trait Foo { fn foo(_: pattern_type!(u32 is ::START..=::END)) {} //[default]~^ ERROR: constant expression depends on a generic parameter //[default]~| ERROR: constant expression depends on a generic parameter +//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors +//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} //[default]~^ ERROR: constant expression depends on a generic parameter //[default]~| ERROR: constant expression depends on a generic parameter +//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors +//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors fn main() {} diff --git a/tests/ui/type/pattern_types/const_generics.rs b/tests/ui/type/pattern_types/const_generics.rs index 5cef0dc03055..79d46c010d73 100644 --- a/tests/ui/type/pattern_types/const_generics.rs +++ b/tests/ui/type/pattern_types/const_generics.rs @@ -1,7 +1,7 @@ //@ check-pass -#![feature(pattern_types)] -#![feature(pattern_type_macro)] +#![feature(pattern_types, generic_pattern_types, pattern_type_macro)] +#![expect(incomplete_features)] use std::pat::pattern_type; diff --git a/tests/ui/type/pattern_types/transmute.rs b/tests/ui/type/pattern_types/transmute.rs index cb76b2b938dc..43dd62a19e70 100644 --- a/tests/ui/type/pattern_types/transmute.rs +++ b/tests/ui/type/pattern_types/transmute.rs @@ -1,5 +1,5 @@ -#![feature(pattern_types)] -#![feature(pattern_type_macro)] +#![feature(pattern_types, pattern_type_macro, generic_pattern_types)] +#![expect(incomplete_features)] use std::pat::pattern_type;