From b676f551e2b784c3ee7500edfc24fa46fdf6b6ef Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 27 May 2025 15:25:40 -0500 Subject: [PATCH 01/13] rustdoc: add ways of collapsing all impl blocks either shift+click the Summary button, or use the `_` key. this collapses everything, including (inherent) impl blocks. no need for a special "expand all impl blocks" method, as impl blocks are expanded during regular "expand all". doing "expand all" -> "collapse all" will always result in only impl blocks being expaned. some of the html is split up a bit awkwardly to try to avoid introducing new whitespaces nodes, which could affect display. Co-authored-by: Guillaume Gomez --- src/librustdoc/html/static/js/main.js | 24 +++++++++++++++++++----- src/librustdoc/html/static/js/storage.js | 4 +++- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 7b1a61a3ffa45..85180b71d1cb1 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -568,7 +568,11 @@ function preLoadCss(cssUrl) { break; case "-": ev.preventDefault(); - collapseAllDocs(); + collapseAllDocs(false); + break; + case "_": + ev.preventDefault(); + collapseAllDocs(true); break; case "?": @@ -1038,11 +1042,14 @@ function preLoadCss(cssUrl) { innerToggle.children[0].innerText = "Summary"; } - function collapseAllDocs() { + /** + * @param {boolean} collapseImpls - also collapse impl blocks if set to true + */ + function collapseAllDocs(collapseImpls) { const innerToggle = document.getElementById(toggleAllDocsId); addClass(innerToggle, "will-expand"); onEachLazy(document.getElementsByClassName("toggle"), e => { - if (e.parentNode.id !== "implementations-list" || + if ((collapseImpls || e.parentNode.id !== "implementations-list") || (!hasClass(e, "implementors-toggle") && !hasClass(e, "type-contents-toggle")) ) { @@ -1053,7 +1060,10 @@ function preLoadCss(cssUrl) { innerToggle.children[0].innerText = "Show all"; } - function toggleAllDocs() { + /** + * @param {MouseEvent=} ev + */ + function toggleAllDocs(ev) { const innerToggle = document.getElementById(toggleAllDocsId); if (!innerToggle) { return; @@ -1061,7 +1071,7 @@ function preLoadCss(cssUrl) { if (hasClass(innerToggle, "will-expand")) { expandAllDocs(); } else { - collapseAllDocs(); + collapseAllDocs(ev !== undefined && ev.shiftKey); } } @@ -1519,6 +1529,10 @@ function preLoadCss(cssUrl) { ["⏎", "Go to active search result"], ["+", "Expand all sections"], ["-", "Collapse all sections"], + // for the sake of brevity, we don't say "inherint impl blocks", + // although that would be more correct, + // since trait impl blocks are collapsed by - + ["_", "Collapse all sections, including impl blocks"], ].map(x => "
" + x[0].split(" ") .map((y, index) => ((index & 1) === 0 ? "" + y + "" : " " + y + " ")) diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 7611372689478..ca13b891638f0 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -418,7 +418,9 @@ class RustdocToolbarElement extends HTMLElement { - `; + `; } } window.customElements.define("rustdoc-toolbar", RustdocToolbarElement); From 978e11baa2eb7bb0ca72379179f7cb3dba1772ff Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 1 Jul 2025 03:23:07 -0500 Subject: [PATCH 02/13] Upgrade the `fortanix-sgx-abi` dependency 0.6.1 removes the `compiler-builtins` dependency, part of RUST-142265. The breaking change from 0.5 to 0.6 is for an update to the `insecure_time` API [1]. I validated that `./x c library --target x86_64-fortanix-unknown-sgx` completes successfully with this change. Link: https://github.com/fortanix/rust-sgx/commit/a34e9767f37d6585c18bdbd31cddcadc56670d57 [1] --- library/Cargo.lock | 5 ++--- library/std/Cargo.toml | 2 +- library/std/src/sys/pal/sgx/abi/usercalls/mod.rs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index c681c5935df5f..3d176803b6146 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -90,11 +90,10 @@ dependencies = [ [[package]] name = "fortanix-sgx-abi" -version = "0.5.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5" +checksum = "5efc85edd5b83e8394f4371dd0da6859dff63dd387dab8568fece6af4cde6f84" dependencies = [ - "compiler_builtins", "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 7c2a43ef20745..10a3db78e273c 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -68,7 +68,7 @@ rand_xorshift = "0.4.0" dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] -fortanix-sgx-abi = { version = "0.5.0", features = [ +fortanix-sgx-abi = { version = "0.6.1", features = [ 'rustc-dep-of-std', ], public = true } diff --git a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs index cbdaf439b2847..d859249f66bf5 100644 --- a/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs +++ b/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs @@ -267,7 +267,7 @@ pub fn send(event_set: u64, tcs: Option) -> IoResult<()> { /// Usercall `insecure_time`. See the ABI documentation for more information. #[unstable(feature = "sgx_platform", issue = "56975")] pub fn insecure_time() -> Duration { - let t = unsafe { raw::insecure_time() }; + let t = unsafe { raw::insecure_time().0 }; Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _) } From 69b9bae57ded527f5fd7f036b6cc1cca0b462ac4 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 13 Jul 2025 00:58:12 +0200 Subject: [PATCH 03/13] Guarantee 8 bytes of alignment in Thread::into_raw --- library/std/src/thread/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 26b2fb4472436..2552d6316fabf 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1380,6 +1380,11 @@ where } /// The internal representation of a `Thread` handle +/// +/// We explicitly set the alignment for our guarantee in Thread::into_raw. This +/// allows applications to stuff extra metadata bits into the alignment, which +/// can be rather useful when working with atomics. +#[repr(align(8))] struct Inner { name: Option, id: ThreadId, @@ -1563,7 +1568,8 @@ impl Thread { /// Consumes the `Thread`, returning a raw pointer. /// /// To avoid a memory leak the pointer must be converted - /// back into a `Thread` using [`Thread::from_raw`]. + /// back into a `Thread` using [`Thread::from_raw`]. The pointer is + /// guaranteed to be aligned to at least 8 bytes. /// /// # Examples /// From 6f4d0bdde85f9e2a0e61bb3e16d407540ddc09ba Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 13 Jul 2025 01:20:29 +0200 Subject: [PATCH 04/13] Tidy --- library/std/src/thread/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 2552d6316fabf..73c0925709207 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1380,7 +1380,7 @@ where } /// The internal representation of a `Thread` handle -/// +/// /// We explicitly set the alignment for our guarantee in Thread::into_raw. This /// allows applications to stuff extra metadata bits into the alignment, which /// can be rather useful when working with atomics. From 1d0eddbedd3b364418d2ae12b1240d487488ac5b Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Fri, 18 Jul 2025 23:26:43 +0200 Subject: [PATCH 05/13] tests: debuginfo: Work around or disable broken tests on powerpc f16 support for PowerPC has issues in LLVM, therefore we need a small workaround to prevent LLVM from emitting symbols that don't exist for PowerPC yet. It also appears that unused by-value non-immedate issue with gdb applies to PowerPC targets as well, though I've only tested 64-bit Linux targets. Signed-off-by: Jens Reidel --- src/tools/compiletest/src/directives.rs | 1 + tests/debuginfo/basic-types-globals-metadata.rs | 5 ++++- tests/debuginfo/basic-types-globals.rs | 5 ++++- tests/debuginfo/by-value-non-immediate-argument.rs | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 93133ea0bfd2e..75c11c31e493a 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -854,6 +854,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-openbsd", "ignore-pass", "ignore-powerpc", + "ignore-powerpc64", "ignore-remote", "ignore-riscv64", "ignore-rustc-debug-assertions", diff --git a/tests/debuginfo/basic-types-globals-metadata.rs b/tests/debuginfo/basic-types-globals-metadata.rs index 53fc550a2dc8c..d14d5472f53bb 100644 --- a/tests/debuginfo/basic-types-globals-metadata.rs +++ b/tests/debuginfo/basic-types-globals-metadata.rs @@ -59,7 +59,10 @@ static mut F64: f64 = 3.5; fn main() { _zzz(); // #break - let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F16, F32, F64) }; + let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; + // N.B. Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which does + // not exist on some targets like PowerPC + let b = unsafe { F16 }; } fn _zzz() {()} diff --git a/tests/debuginfo/basic-types-globals.rs b/tests/debuginfo/basic-types-globals.rs index 41b69939650da..5933c6d2440dc 100644 --- a/tests/debuginfo/basic-types-globals.rs +++ b/tests/debuginfo/basic-types-globals.rs @@ -63,7 +63,10 @@ static mut F64: f64 = 3.5; fn main() { _zzz(); // #break - let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F16, F32, F64) }; + let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; + // N.B. Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which does + // not exist on some targets like PowerPC + let b = unsafe { F16 }; } fn _zzz() {()} diff --git a/tests/debuginfo/by-value-non-immediate-argument.rs b/tests/debuginfo/by-value-non-immediate-argument.rs index 5233b95f1f4ad..deacea5f6ccd8 100644 --- a/tests/debuginfo/by-value-non-immediate-argument.rs +++ b/tests/debuginfo/by-value-non-immediate-argument.rs @@ -3,6 +3,7 @@ //@ compile-flags:-g //@ ignore-windows-gnu: #128973 //@ ignore-aarch64-unknown-linux-gnu (gdb tries to read from 0x0; FIXME: #128973) +//@ ignore-powerpc64: #128973 on both -gnu and -musl // === GDB TESTS =================================================================================== From e1b6cfe62e0571d2c5bfd89fd7dae9e4cf7bcf86 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Mon, 21 Jul 2025 21:57:08 +0200 Subject: [PATCH 06/13] Rephrase comment to include some tracking issues Signed-off-by: Jens Reidel --- tests/debuginfo/basic-types-globals-metadata.rs | 6 ++++-- tests/debuginfo/basic-types-globals.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/debuginfo/basic-types-globals-metadata.rs b/tests/debuginfo/basic-types-globals-metadata.rs index d14d5472f53bb..aec8ff183ad75 100644 --- a/tests/debuginfo/basic-types-globals-metadata.rs +++ b/tests/debuginfo/basic-types-globals-metadata.rs @@ -60,8 +60,10 @@ fn main() { _zzz(); // #break let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; - // N.B. Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which does - // not exist on some targets like PowerPC + // FIXME: Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which + // does not exist on some targets like PowerPC. + // See https://github.com/llvm/llvm-project/issues/97981 and + // https://github.com/rust-lang/compiler-builtins/issues/655 let b = unsafe { F16 }; } diff --git a/tests/debuginfo/basic-types-globals.rs b/tests/debuginfo/basic-types-globals.rs index 5933c6d2440dc..15a0deb64c125 100644 --- a/tests/debuginfo/basic-types-globals.rs +++ b/tests/debuginfo/basic-types-globals.rs @@ -64,8 +64,10 @@ fn main() { _zzz(); // #break let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; - // N.B. Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which does - // not exist on some targets like PowerPC + // FIXME: Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which + // does not exist on some targets like PowerPC. + // See https://github.com/llvm/llvm-project/issues/97981 and + // https://github.com/rust-lang/compiler-builtins/issues/655 let b = unsafe { F16 }; } From e958b20af7ad3e3a053070a9c45389fe463ccc0c Mon Sep 17 00:00:00 2001 From: Ben Schulz Date: Wed, 9 Jul 2025 18:46:11 +0200 Subject: [PATCH 07/13] Fix unused_parens false positive --- compiler/rustc_lint/src/unused.rs | 7 ++++++- .../unused/unused-parens-false-positive-issue-143653.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index a9eb1739f7f10..5873e7bd6a72e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1062,6 +1062,7 @@ pub(crate) struct UnusedParens { /// ``` /// type Example = Box &'static dyn Send>; /// ``` +#[derive(Copy, Clone)] enum NoBoundsException { /// The type must be parenthesized. None, @@ -1340,7 +1341,11 @@ impl EarlyLintPass for UnusedParens { self.with_self_ty_parens = false; } ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => { - self.in_no_bounds_pos.insert(mut_ty.ty.id, NoBoundsException::OneBound); + // If this type itself appears in no-bounds position, we propagate its + // potentially tighter constraint or risk a false posive (issue 143653). + let own_constraint = self.in_no_bounds_pos.get(&ty.id).copied(); + let constraint = own_constraint.unwrap_or(NoBoundsException::OneBound); + self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint); } ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { for i in 0..bounds.len() { diff --git a/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs new file mode 100644 index 0000000000000..78f335c26a767 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#![deny(unused_parens)] +#![allow(warnings)] +trait MyTrait {} + +fn foo(_: Box &mut (dyn MyTrait) + Send + Sync>) {} + +fn main() {} From 6fc68c16e7774be27b19ae152507b471d9a1a233 Mon Sep 17 00:00:00 2001 From: Ben Schulz Date: Thu, 10 Jul 2025 08:02:25 +0200 Subject: [PATCH 08/13] Add test case for single bound --- ...d-parens-false-positive-issue-143653.fixed | 12 ++++++++++++ ...used-parens-false-positive-issue-143653.rs | 5 ++++- ...-parens-false-positive-issue-143653.stderr | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused/unused-parens-false-positive-issue-143653.fixed create mode 100644 tests/ui/lint/unused/unused-parens-false-positive-issue-143653.stderr diff --git a/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.fixed b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.fixed new file mode 100644 index 0000000000000..4b0bca3d44a73 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.fixed @@ -0,0 +1,12 @@ +//@ run-rustfix + +#![deny(unused_parens)] +#![allow(warnings)] +trait MyTrait {} + +fn foo(_: Box &mut (dyn MyTrait) + Send + Sync>) {} + +//~v ERROR unnecessary parentheses around type +fn bar(_: Box &mut dyn MyTrait>) {} + +fn main() {} diff --git a/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs index 78f335c26a767..4eefd3dc81a6c 100644 --- a/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs +++ b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.rs @@ -1,4 +1,4 @@ -//@ check-pass +//@ run-rustfix #![deny(unused_parens)] #![allow(warnings)] @@ -6,4 +6,7 @@ trait MyTrait {} fn foo(_: Box &mut (dyn MyTrait) + Send + Sync>) {} +//~v ERROR unnecessary parentheses around type +fn bar(_: Box &mut (dyn MyTrait)>) {} + fn main() {} diff --git a/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.stderr b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.stderr new file mode 100644 index 0000000000000..89455e3db7378 --- /dev/null +++ b/tests/ui/lint/unused/unused-parens-false-positive-issue-143653.stderr @@ -0,0 +1,19 @@ +error: unnecessary parentheses around type + --> $DIR/unused-parens-false-positive-issue-143653.rs:10:43 + | +LL | fn bar(_: Box &mut (dyn MyTrait)>) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-false-positive-issue-143653.rs:3:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn bar(_: Box &mut (dyn MyTrait)>) {} +LL + fn bar(_: Box &mut dyn MyTrait>) {} + | + +error: aborting due to 1 previous error + From 307f66436b602697c8f1c49d8f455ec60a176166 Mon Sep 17 00:00:00 2001 From: Ben Schulz Date: Thu, 24 Jul 2025 20:41:30 +0200 Subject: [PATCH 09/13] Replace unwrap_or with explicit match --- compiler/rustc_lint/src/unused.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 5873e7bd6a72e..df9f3a500d94a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1062,7 +1062,6 @@ pub(crate) struct UnusedParens { /// ``` /// type Example = Box &'static dyn Send>; /// ``` -#[derive(Copy, Clone)] enum NoBoundsException { /// The type must be parenthesized. None, @@ -1343,8 +1342,12 @@ impl EarlyLintPass for UnusedParens { ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => { // If this type itself appears in no-bounds position, we propagate its // potentially tighter constraint or risk a false posive (issue 143653). - let own_constraint = self.in_no_bounds_pos.get(&ty.id).copied(); - let constraint = own_constraint.unwrap_or(NoBoundsException::OneBound); + let own_constraint = self.in_no_bounds_pos.get(&ty.id); + let constraint = match own_constraint { + Some(NoBoundsException::None) => NoBoundsException::None, + Some(NoBoundsException::OneBound) => NoBoundsException::OneBound, + None => NoBoundsException::OneBound, + }; self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint); } ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { From a5f73bfce80347205a528776b45cc321b86876b1 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Wed, 16 Jul 2025 16:16:24 -0700 Subject: [PATCH 10/13] Verify llvm-needs-components are not empty and match the --target value --- .../rustc-dev-guide/src/tests/directives.md | 13 +- src/tools/compiletest/src/directives.rs | 184 ++++++++++++++---- .../compiletest/src/directives/auxiliary.rs | 41 +++- src/tools/compiletest/src/runtest/debugger.rs | 8 +- src/tools/tidy/src/style.rs | 7 +- src/tools/tidy/src/target_specific_tests.rs | 61 +++++- tests/codegen-llvm/abi-efiapi.rs | 10 +- tests/codegen-llvm/cast-target-abi.rs | 2 +- tests/codegen-llvm/cf-protection.rs | 2 +- tests/codegen-llvm/codemodels.rs | 2 +- tests/codegen-llvm/ehcontguard_disabled.rs | 2 - .../codegen-llvm/naked-fn/naked-functions.rs | 2 +- .../address-sanitizer-globals-tracking.rs | 6 +- ...it-kcfi-operand-bundle-attr-no-sanitize.rs | 2 +- ...rand-bundle-itanium-cxx-abi-generalized.rs | 2 +- ...-itanium-cxx-abi-normalized-generalized.rs | 2 +- ...erand-bundle-itanium-cxx-abi-normalized.rs | 2 +- ...mit-kcfi-operand-bundle-itanium-cxx-abi.rs | 2 +- .../kcfi/emit-kcfi-operand-bundle.rs | 2 +- .../kcfi/emit-type-metadata-trait-objects.rs | 2 +- .../sanitizer/memory-track-origins.rs | 2 +- tests/codegen-llvm/ub-checks.rs | 2 +- tests/ui/errors/remap-path-prefix-sysroot.rs | 2 +- tests/ui/errors/wrong-target-spec.rs | 1 + tests/ui/linkage-attr/incompatible-flavor.rs | 2 +- tests/ui/linkage-attr/unstable-flavor.rs | 4 +- tests/ui/target_modifiers/defaults_check.rs | 2 +- .../target_modifiers/incompatible_fixedx18.rs | 2 +- .../target_modifiers/incompatible_regparm.rs | 2 +- tests/ui/target_modifiers/no_value_bool.rs | 2 +- 30 files changed, 278 insertions(+), 97 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 5c3ae359ba0bf..89e4d3e9b58ec 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -293,8 +293,6 @@ See [Pretty-printer](compiletest.md#pretty-printer-tests). - `no-auto-check-cfg` — disable auto check-cfg (only for `--check-cfg` tests) - [`revisions`](compiletest.md#revisions) — compile multiple times -- [`unused-revision-names`](compiletest.md#ignoring-unused-revision-names) - - suppress tidy checks for mentioning unknown revision names -[`forbid-output`](compiletest.md#incremental-tests) — incremental cfail rejects output pattern - [`should-ice`](compiletest.md#incremental-tests) — incremental cfail should @@ -315,6 +313,17 @@ test suites that use those tools: - `llvm-cov-flags` adds extra flags when running LLVM's `llvm-cov` tool. - Used by [coverage tests](compiletest.md#coverage-tests) in `coverage-run` mode. +### Tidy specific directives + +The following directives control how the [tidy script](../conventions.md#formatting) +verifies tests. + +- `ignore-tidy-target-specific-tests` disables checking that the appropriate + LLVM component is required (via a `needs-llvm-components` directive) when a + test is compiled for a specific target (via the `--target` flag in a + `compile-flag` directive). +- [`unused-revision-names`](compiletest.md#ignoring-unused-revision-names) - + suppress tidy checks for mentioning unknown revision names. ## Substitutions diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 1397c87ab075b..9cbbbd1d0d03a 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -59,9 +59,9 @@ impl EarlyProps { &mut poisoned, testfile, rdr, - &mut |DirectiveLine { raw_directive: ln, .. }| { - parse_and_update_aux(config, ln, &mut props.aux); - config.parse_and_update_revisions(testfile, ln, &mut props.revisions); + &mut |DirectiveLine { line_number, raw_directive: ln, .. }| { + parse_and_update_aux(config, ln, testfile, line_number, &mut props.aux); + config.parse_and_update_revisions(testfile, line_number, ln, &mut props.revisions); }, ); @@ -351,7 +351,7 @@ impl TestProps { &mut poisoned, testfile, file, - &mut |directive @ DirectiveLine { raw_directive: ln, .. }| { + &mut |directive @ DirectiveLine { line_number, raw_directive: ln, .. }| { if !directive.applies_to_test_revision(test_revision) { return; } @@ -361,17 +361,28 @@ impl TestProps { config.push_name_value_directive( ln, ERROR_PATTERN, + testfile, + line_number, &mut self.error_patterns, |r| r, ); config.push_name_value_directive( ln, REGEX_ERROR_PATTERN, + testfile, + line_number, &mut self.regex_error_patterns, |r| r, ); - config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r); + config.push_name_value_directive( + ln, + DOC_FLAGS, + testfile, + line_number, + &mut self.doc_flags, + |r| r, + ); fn split_flags(flags: &str) -> Vec { // Individual flags can be single-quoted to preserve spaces; see @@ -386,7 +397,9 @@ impl TestProps { .collect::>() } - if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { + if let Some(flags) = + config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile, line_number) + { let flags = split_flags(&flags); for flag in &flags { if flag == "--edition" || flag.starts_with("--edition=") { @@ -395,25 +408,40 @@ impl TestProps { } self.compile_flags.extend(flags); } - if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { + if config + .parse_name_value_directive( + ln, + INCORRECT_COMPILER_FLAGS, + testfile, + line_number, + ) + .is_some() + { panic!("`compiler-flags` directive should be spelled `compile-flags`"); } - if let Some(edition) = config.parse_edition(ln) { + if let Some(edition) = config.parse_edition(ln, testfile, line_number) { // The edition is added at the start, since flags from //@compile-flags must // be passed to rustc last. self.compile_flags.insert(0, format!("--edition={}", edition.trim())); has_edition = true; } - config.parse_and_update_revisions(testfile, ln, &mut self.revisions); + config.parse_and_update_revisions( + testfile, + line_number, + ln, + &mut self.revisions, + ); - if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) { + if let Some(flags) = + config.parse_name_value_directive(ln, RUN_FLAGS, testfile, line_number) + { self.run_flags.extend(split_flags(&flags)); } if self.pp_exact.is_none() { - self.pp_exact = config.parse_pp_exact(ln, testfile); + self.pp_exact = config.parse_pp_exact(ln, testfile, line_number); } config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); @@ -435,7 +463,9 @@ impl TestProps { ); config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic); - if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) { + if let Some(m) = + config.parse_name_value_directive(ln, PRETTY_MODE, testfile, line_number) + { self.pretty_mode = m; } @@ -446,35 +476,45 @@ impl TestProps { ); // Call a helper method to deal with aux-related directives. - parse_and_update_aux(config, ln, &mut self.aux); + parse_and_update_aux(config, ln, testfile, line_number, &mut self.aux); config.push_name_value_directive( ln, EXEC_ENV, + testfile, + line_number, &mut self.exec_env, Config::parse_env, ); config.push_name_value_directive( ln, UNSET_EXEC_ENV, + testfile, + line_number, &mut self.unset_exec_env, |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, RUSTC_ENV, + testfile, + line_number, &mut self.rustc_env, Config::parse_env, ); config.push_name_value_directive( ln, UNSET_RUSTC_ENV, + testfile, + line_number, &mut self.unset_rustc_env, |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, FORBID_OUTPUT, + testfile, + line_number, &mut self.forbid_output, |r| r, ); @@ -510,7 +550,7 @@ impl TestProps { } if let Some(code) = config - .parse_name_value_directive(ln, FAILURE_STATUS) + .parse_name_value_directive(ln, FAILURE_STATUS, testfile, line_number) .and_then(|code| code.trim().parse::().ok()) { self.failure_status = Some(code); @@ -531,6 +571,8 @@ impl TestProps { config.set_name_value_directive( ln, ASSEMBLY_OUTPUT, + testfile, + line_number, &mut self.assembly_output, |r| r.trim().to_string(), ); @@ -543,7 +585,9 @@ impl TestProps { // Unlike the other `name_value_directive`s this needs to be handled manually, // because it sets a `bool` flag. - if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) { + if let Some(known_bug) = + config.parse_name_value_directive(ln, KNOWN_BUG, testfile, line_number) + { let known_bug = known_bug.trim(); if known_bug == "unknown" || known_bug.split(',').all(|issue_ref| { @@ -571,16 +615,25 @@ impl TestProps { config.set_name_value_directive( ln, TEST_MIR_PASS, + testfile, + line_number, &mut self.mir_unit_test, |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); - if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { + if let Some(flags) = + config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile, line_number) + { self.llvm_cov_flags.extend(split_flags(&flags)); } - if let Some(flags) = config.parse_name_value_directive(ln, FILECHECK_FLAGS) { + if let Some(flags) = config.parse_name_value_directive( + ln, + FILECHECK_FLAGS, + testfile, + line_number, + ) { self.filecheck_flags.extend(split_flags(&flags)); } @@ -588,9 +641,12 @@ impl TestProps { self.update_add_core_stubs(ln, config); - if let Some(err_kind) = - config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) - { + if let Some(err_kind) = config.parse_name_value_directive( + ln, + DONT_REQUIRE_ANNOTATIONS, + testfile, + line_number, + ) { self.dont_require_annotations .insert(ErrorKind::expect_from_user_str(err_kind.trim())); } @@ -1204,6 +1260,7 @@ impl Config { fn parse_and_update_revisions( &self, testfile: &Utf8Path, + line_number: usize, line: &str, existing: &mut Vec, ) { @@ -1217,7 +1274,8 @@ impl Config { const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] = ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"]; - if let Some(raw) = self.parse_name_value_directive(line, "revisions") { + if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile, line_number) + { if self.mode == TestMode::RunMake { panic!("`run-make` tests do not support revisions: {}", testfile); } @@ -1262,8 +1320,13 @@ impl Config { (name.to_owned(), value.to_owned()) } - fn parse_pp_exact(&self, line: &str, testfile: &Utf8Path) -> Option { - if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { + fn parse_pp_exact( + &self, + line: &str, + testfile: &Utf8Path, + line_number: usize, + ) -> Option { + if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile, line_number) { Some(Utf8PathBuf::from(&s)) } else if self.parse_name_directive(line, "pp-exact") { testfile.file_name().map(Utf8PathBuf::from) @@ -1304,19 +1367,31 @@ impl Config { line.starts_with("no-") && self.parse_name_directive(&line[3..], directive) } - pub fn parse_name_value_directive(&self, line: &str, directive: &str) -> Option { + pub fn parse_name_value_directive( + &self, + line: &str, + directive: &str, + testfile: &Utf8Path, + line_number: usize, + ) -> Option { let colon = directive.len(); if line.starts_with(directive) && line.as_bytes().get(colon) == Some(&b':') { let value = line[(colon + 1)..].to_owned(); debug!("{}: {}", directive, value); - Some(expand_variables(value, self)) + let value = expand_variables(value, self); + if value.is_empty() { + error!("{testfile}:{line_number}: empty value for directive `{}`", directive); + help!("expected syntax is: `//@ {}: value`", directive); + panic!("empty directive value detected"); + } + Some(value) } else { None } } - fn parse_edition(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "edition") + fn parse_edition(&self, line: &str, testfile: &Utf8Path, line_number: usize) -> Option { + self.parse_name_value_directive(line, "edition", testfile, line_number) } fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) { @@ -1338,11 +1413,14 @@ impl Config { &self, line: &str, directive: &str, + testfile: &Utf8Path, + line_number: usize, value: &mut Option, parse: impl FnOnce(String) -> T, ) { if value.is_none() { - *value = self.parse_name_value_directive(line, directive).map(parse); + *value = + self.parse_name_value_directive(line, directive, testfile, line_number).map(parse); } } @@ -1350,10 +1428,14 @@ impl Config { &self, line: &str, directive: &str, + testfile: &Utf8Path, + line_number: usize, values: &mut Vec, parse: impl FnOnce(String) -> T, ) { - if let Some(value) = self.parse_name_value_directive(line, directive).map(parse) { + if let Some(value) = + self.parse_name_value_directive(line, directive, testfile, line_number).map(parse) + { values.push(value); } } @@ -1670,9 +1752,9 @@ pub(crate) fn make_test_description( decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); - decision!(ignore_llvm(config, path, ln)); - decision!(ignore_backends(config, path, ln)); - decision!(needs_backends(config, path, ln)); + decision!(ignore_llvm(config, path, ln, line_number)); + decision!(ignore_backends(config, path, ln, line_number)); + decision!(needs_backends(config, path, ln, line_number)); decision!(ignore_cdb(config, ln)); decision!(ignore_gdb(config, ln)); decision!(ignore_lldb(config, ln)); @@ -1799,8 +1881,15 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { - if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") { +fn ignore_backends( + config: &Config, + path: &Utf8Path, + line: &str, + line_number: usize, +) -> IgnoreDecision { + if let Some(backends_to_ignore) = + config.parse_name_value_directive(line, "ignore-backends", path, line_number) + { for backend in backends_to_ignore.split_whitespace().map(|backend| { match CodegenBackend::try_from(backend) { Ok(backend) => backend, @@ -1819,8 +1908,15 @@ fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecisi IgnoreDecision::Continue } -fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { - if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") { +fn needs_backends( + config: &Config, + path: &Utf8Path, + line: &str, + line_number: usize, +) -> IgnoreDecision { + if let Some(needed_backends) = + config.parse_name_value_directive(line, "needs-backends", path, line_number) + { if !needed_backends .split_whitespace() .map(|backend| match CodegenBackend::try_from(backend) { @@ -1842,9 +1938,9 @@ fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecisio IgnoreDecision::Continue } -fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { +fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str, line_number: usize) -> IgnoreDecision { if let Some(needed_components) = - config.parse_name_value_directive(line, "needs-llvm-components") + config.parse_name_value_directive(line, "needs-llvm-components", path, line_number) { let components: HashSet<_> = config.llvm_components.split_whitespace().collect(); if let Some(missing_component) = needed_components @@ -1865,7 +1961,9 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { if let Some(actual_version) = &config.llvm_version { // Note that these `min` versions will check for not just major versions. - if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") { + if let Some(version_string) = + config.parse_name_value_directive(line, "min-llvm-version", path, line_number) + { let min_version = extract_llvm_version(&version_string); // Ignore if actual version is smaller than the minimum required version. if *actual_version < min_version { @@ -1876,7 +1974,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "max-llvm-major-version") + config.parse_name_value_directive(line, "max-llvm-major-version", path, line_number) { let max_version = extract_llvm_version(&version_string); // Ignore if actual major version is larger than the maximum required major version. @@ -1890,7 +1988,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "min-system-llvm-version") + config.parse_name_value_directive(line, "min-system-llvm-version", path, line_number) { let min_version = extract_llvm_version(&version_string); // Ignore if using system LLVM and actual version @@ -1903,7 +2001,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { }; } } else if let Some(version_range) = - config.parse_name_value_directive(line, "ignore-llvm-version") + config.parse_name_value_directive(line, "ignore-llvm-version", path, line_number) { // Syntax is: "ignore-llvm-version: [- ]" let (v_min, v_max) = @@ -1929,7 +2027,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision { } } } else if let Some(version_string) = - config.parse_name_value_directive(line, "exact-llvm-major-version") + config.parse_name_value_directive(line, "exact-llvm-major-version", path, line_number) { // Syntax is "exact-llvm-major-version: " let version = extract_llvm_version(&version_string); diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index cdb75f6ffa907..7c1ed2e700624 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -3,6 +3,8 @@ use std::iter; +use camino::Utf8Path; + use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; @@ -41,17 +43,42 @@ impl AuxProps { /// If the given test directive line contains an `aux-*` directive, parse it /// and update [`AuxProps`] accordingly. -pub(super) fn parse_and_update_aux(config: &Config, ln: &str, aux: &mut AuxProps) { +pub(super) fn parse_and_update_aux( + config: &Config, + ln: &str, + testfile: &Utf8Path, + line_number: usize, + aux: &mut AuxProps, +) { if !(ln.starts_with("aux-") || ln.starts_with("proc-macro")) { return; } - config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); - config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); - config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); - config - .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); - if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { + config.push_name_value_directive(ln, AUX_BUILD, testfile, line_number, &mut aux.builds, |r| { + r.trim().to_string() + }); + config.push_name_value_directive(ln, AUX_BIN, testfile, line_number, &mut aux.bins, |r| { + r.trim().to_string() + }); + config.push_name_value_directive( + ln, + AUX_CRATE, + testfile, + line_number, + &mut aux.crates, + parse_aux_crate, + ); + config.push_name_value_directive( + ln, + PROC_MACRO, + testfile, + line_number, + &mut aux.proc_macros, + |r| r.trim().to_string(), + ); + if let Some(r) = + config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile, line_number) + { aux.codegen_backend = Some(r.trim().to_owned()); } } diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index a4103c5b4a9a4..ba824124e875d 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -47,10 +47,14 @@ impl DebuggerCommands { continue; }; - if let Some(command) = config.parse_name_value_directive(&line, &command_directive) { + if let Some(command) = + config.parse_name_value_directive(&line, &command_directive, file, line_no) + { commands.push(command); } - if let Some(pattern) = config.parse_name_value_directive(&line, &check_directive) { + if let Some(pattern) = + config.parse_name_value_directive(&line, &check_directive, file, line_no) + { check_lines.push((line_no, pattern)); } } diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 35ed61eacc73f..fca097c091b75 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -519,8 +519,11 @@ pub fn check(path: &Path, bad: &mut bool) { .any(|directive| matches!(directive, Directive::Ignore(_))); let has_alphabetical_directive = line.contains("tidy-alphabetical-start") || line.contains("tidy-alphabetical-end"); - let has_recognized_directive = - has_recognized_ignore_directive || has_alphabetical_directive; + let has_other_tidy_ignore_directive = + line.contains("ignore-tidy-target-specific-tests"); + let has_recognized_directive = has_recognized_ignore_directive + || has_alphabetical_directive + || has_other_tidy_ignore_directive; if contains_potential_directive && (!has_recognized_directive) { err("Unrecognized tidy directive") } diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs index f4a6783abb679..b2d5f259eb2db 100644 --- a/src/tools/tidy/src/target_specific_tests.rs +++ b/src/tools/tidy/src/target_specific_tests.rs @@ -12,12 +12,16 @@ const COMPILE_FLAGS_HEADER: &str = "compile-flags:"; #[derive(Default, Debug)] struct RevisionInfo<'a> { - target_arch: Option<&'a str>, + target_arch: Option>, llvm_components: Option>, } pub fn check(tests_path: &Path, bad: &mut bool) { crate::walk::walk(tests_path, |path, _is_dir| filter_not_rust(path), &mut |entry, content| { + if content.contains("// ignore-tidy-target-specific-tests") { + return; + } + let file = entry.path().display(); let mut header_map = BTreeMap::new(); iter_header(content, &mut |HeaderLine { revision, directive, .. }| { @@ -34,10 +38,11 @@ pub fn check(tests_path: &Path, bad: &mut bool) { && let Some((_, v)) = compile_flags.split_once("--target") { let v = v.trim_start_matches([' ', '=']); - let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") }; - if let Some((arch, _)) = v { - let info = header_map.entry(revision).or_insert(RevisionInfo::default()); - info.target_arch.replace(arch); + let info = header_map.entry(revision).or_insert(RevisionInfo::default()); + if v.starts_with("{{") { + info.target_arch.replace(None); + } else if let Some((arch, _)) = v.split_once("-") { + info.target_arch.replace(Some(arch)); } else { eprintln!("{file}: seems to have a malformed --target value"); *bad = true; @@ -54,9 +59,11 @@ pub fn check(tests_path: &Path, bad: &mut bool) { let rev = rev.unwrap_or("[unspecified]"); match (target_arch, llvm_components) { (None, None) => {} - (Some(_), None) => { + (Some(target_arch), None) => { + let llvm_component = + target_arch.map_or_else(|| "".to_string(), arch_to_llvm_component); eprintln!( - "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER}` as it has `--target` set" + "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER} {llvm_component}` as it has `--target` set" ); *bad = true; } @@ -66,11 +73,45 @@ pub fn check(tests_path: &Path, bad: &mut bool) { ); *bad = true; } - (Some(_), Some(_)) => { - // FIXME: check specified components against the target architectures we - // gathered. + (Some(target_arch), Some(llvm_components)) => { + if let Some(target_arch) = target_arch { + let llvm_component = arch_to_llvm_component(target_arch); + if !llvm_components.contains(&llvm_component.as_str()) { + eprintln!( + "{file}: revision {rev} should specify `{LLVM_COMPONENTS_HEADER} {llvm_component}` as it has `--target` set" + ); + *bad = true; + } + } } } } }); } + +fn arch_to_llvm_component(arch: &str) -> String { + // NOTE: This is an *approximate* mapping of Rust's `--target` architecture to LLVM component + // names. It is not intended to be an authoritative source, but rather a best-effort that's good + // enough for the purpose of this tidy check. + match arch { + "amdgcn" => "amdgpu".into(), + "aarch64_be" | "arm64_32" | "arm64e" | "arm64ec" => "aarch64".into(), + "i386" | "i586" | "i686" | "x86" | "x86_64" | "x86_64h" => "x86".into(), + "loongarch32" | "loongarch64" => "loongarch".into(), + "nvptx64" => "nvptx".into(), + "s390x" => "systemz".into(), + "sparc64" | "sparcv9" => "sparc".into(), + "wasm32" | "wasm32v1" | "wasm64" => "webassembly".into(), + _ if arch.starts_with("armeb") + || arch.starts_with("armv") + || arch.starts_with("thumbv") => + { + "arm".into() + } + _ if arch.starts_with("bpfe") => "bpf".into(), + _ if arch.starts_with("mips") => "mips".into(), + _ if arch.starts_with("powerpc") => "powerpc".into(), + _ if arch.starts_with("riscv") => "riscv".into(), + _ => arch.to_ascii_lowercase(), + } +} diff --git a/tests/codegen-llvm/abi-efiapi.rs b/tests/codegen-llvm/abi-efiapi.rs index 1736f0daf0fac..4cd645101a8b1 100644 --- a/tests/codegen-llvm/abi-efiapi.rs +++ b/tests/codegen-llvm/abi-efiapi.rs @@ -3,15 +3,15 @@ //@ add-core-stubs //@ revisions:x86_64 i686 aarch64 arm riscv //@[x86_64] compile-flags: --target x86_64-unknown-uefi -//@[x86_64] needs-llvm-components: aarch64 arm riscv +//@[x86_64] needs-llvm-components: x86 //@[i686] compile-flags: --target i686-unknown-linux-musl -//@[i686] needs-llvm-components: aarch64 arm riscv +//@[i686] needs-llvm-components: x86 //@[aarch64] compile-flags: --target aarch64-unknown-none -//@[aarch64] needs-llvm-components: aarch64 arm riscv +//@[aarch64] needs-llvm-components: aarch64 //@[arm] compile-flags: --target armv7r-none-eabi -//@[arm] needs-llvm-components: aarch64 arm riscv +//@[arm] needs-llvm-components: arm //@[riscv] compile-flags: --target riscv64gc-unknown-none-elf -//@[riscv] needs-llvm-components: aarch64 arm riscv +//@[riscv] needs-llvm-components: riscv //@ compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/tests/codegen-llvm/cast-target-abi.rs b/tests/codegen-llvm/cast-target-abi.rs index cbd49e2f022a1..28d3ad5f61c7f 100644 --- a/tests/codegen-llvm/cast-target-abi.rs +++ b/tests/codegen-llvm/cast-target-abi.rs @@ -4,7 +4,7 @@ //@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes -Zlint-llvm-ir //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu -//@[aarch64] needs-llvm-components: arm +//@[aarch64] needs-llvm-components: aarch64 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu diff --git a/tests/codegen-llvm/cf-protection.rs b/tests/codegen-llvm/cf-protection.rs index f1349a5dcb980..9efadb599322a 100644 --- a/tests/codegen-llvm/cf-protection.rs +++ b/tests/codegen-llvm/cf-protection.rs @@ -3,7 +3,7 @@ //@ add-core-stubs //@ revisions: undefined none branch return full //@ needs-llvm-components: x86 -//@ [undefined] compile-flags: +// [undefined] no extra compile-flags //@ [none] compile-flags: -Z cf-protection=none //@ [branch] compile-flags: -Z cf-protection=branch //@ [return] compile-flags: -Z cf-protection=return diff --git a/tests/codegen-llvm/codemodels.rs b/tests/codegen-llvm/codemodels.rs index 06d2eade78ae8..e82e094aab8ad 100644 --- a/tests/codegen-llvm/codemodels.rs +++ b/tests/codegen-llvm/codemodels.rs @@ -1,7 +1,7 @@ //@ only-x86_64 //@ revisions: NOMODEL MODEL-SMALL MODEL-KERNEL MODEL-MEDIUM MODEL-LARGE -//@[NOMODEL] compile-flags: +// [NOMODEL] no compile-flags //@[MODEL-SMALL] compile-flags: -C code-model=small //@[MODEL-KERNEL] compile-flags: -C code-model=kernel //@[MODEL-MEDIUM] compile-flags: -C code-model=medium diff --git a/tests/codegen-llvm/ehcontguard_disabled.rs b/tests/codegen-llvm/ehcontguard_disabled.rs index 9efb2721b3e82..962d14e7eb9bc 100644 --- a/tests/codegen-llvm/ehcontguard_disabled.rs +++ b/tests/codegen-llvm/ehcontguard_disabled.rs @@ -1,5 +1,3 @@ -//@ compile-flags: - #![crate_type = "lib"] // A basic test function. diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index 344af6eb42fa8..8a7ee4b4de563 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -8,7 +8,7 @@ //@[win_i686] compile-flags: --target i686-pc-windows-gnu //@[win_i686] needs-llvm-components: x86 //@[macos] compile-flags: --target aarch64-apple-darwin -//@[macos] needs-llvm-components: arm +//@[macos] needs-llvm-components: aarch64 //@[thumb] compile-flags: --target thumbv7em-none-eabi //@[thumb] needs-llvm-components: arm diff --git a/tests/codegen-llvm/sanitizer/address-sanitizer-globals-tracking.rs b/tests/codegen-llvm/sanitizer/address-sanitizer-globals-tracking.rs index f319306f93fd8..642bf5e75762b 100644 --- a/tests/codegen-llvm/sanitizer/address-sanitizer-globals-tracking.rs +++ b/tests/codegen-llvm/sanitizer/address-sanitizer-globals-tracking.rs @@ -19,9 +19,9 @@ //@ only-linux // //@ revisions:ASAN ASAN-FAT-LTO -//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static -//@[ASAN] compile-flags: -//@[ASAN-FAT-LTO] compile-flags: -Cprefer-dynamic=false -Clto=fat +//@ compile-flags: -Zsanitizer=address -Ctarget-feature=-crt-static +// [ASAN] no extra compile-flags +//@[ASAN-FAT-LTO] compile-flags: -Cprefer-dynamic=false -Clto=fat #![crate_type = "staticlib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs index 6b40918dd3af1..02c31fb8e9b03 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-attr-no-sanitize.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs index 942b50deb0284..9a60d51713f56 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-generalized.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-generalize-pointers #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs index c89d9bdd12176..134f4ff4bfd9a 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized-generalized.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zsanitizer-cfi-generalize-pointers #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs index 220cae1a4fa37..4328b7fa07dff 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi-normalized.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs index bb9a000590302..81a9db1b97a57 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle-itanium-cxx-abi.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle.rs index 8b844b991429b..61056c2a54e7b 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-kcfi-operand-bundle.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/kcfi/emit-type-metadata-trait-objects.rs b/tests/codegen-llvm/sanitizer/kcfi/emit-type-metadata-trait-objects.rs index 15c107bea158b..182af162d7824 100644 --- a/tests/codegen-llvm/sanitizer/kcfi/emit-type-metadata-trait-objects.rs +++ b/tests/codegen-llvm/sanitizer/kcfi/emit-type-metadata-trait-objects.rs @@ -5,7 +5,7 @@ //@ [aarch64] compile-flags: --target aarch64-unknown-none //@ [aarch64] needs-llvm-components: aarch64 //@ [x86_64] compile-flags: --target x86_64-unknown-none -//@ [x86_64] needs-llvm-components: +//@ [x86_64] needs-llvm-components: x86 //@ compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/memory-track-origins.rs b/tests/codegen-llvm/sanitizer/memory-track-origins.rs index 318c277e10cba..5eb5b356b0510 100644 --- a/tests/codegen-llvm/sanitizer/memory-track-origins.rs +++ b/tests/codegen-llvm/sanitizer/memory-track-origins.rs @@ -5,7 +5,7 @@ //@ revisions:MSAN-0 MSAN-1 MSAN-2 MSAN-1-LTO MSAN-2-LTO // //@ compile-flags: -Zsanitizer=memory -Ctarget-feature=-crt-static -//@[MSAN-0] compile-flags: +// [MSAN-0] no extra compile-flags //@[MSAN-1] compile-flags: -Zsanitizer-memory-track-origins=1 //@[MSAN-2] compile-flags: -Zsanitizer-memory-track-origins //@[MSAN-1-LTO] compile-flags: -Zsanitizer-memory-track-origins=1 -C lto=fat diff --git a/tests/codegen-llvm/ub-checks.rs b/tests/codegen-llvm/ub-checks.rs index 67f5bff08d5bb..c40bc9acc52a1 100644 --- a/tests/codegen-llvm/ub-checks.rs +++ b/tests/codegen-llvm/ub-checks.rs @@ -6,7 +6,7 @@ // but ub-checks are explicitly disabled. //@ revisions: DEBUG NOCHECKS -//@ [DEBUG] compile-flags: +// [DEBUG] no extra compile-flags //@ [NOCHECKS] compile-flags: -Zub-checks=no //@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes diff --git a/tests/ui/errors/remap-path-prefix-sysroot.rs b/tests/ui/errors/remap-path-prefix-sysroot.rs index 5e2e4fab51de3..f4a2766ff4c06 100644 --- a/tests/ui/errors/remap-path-prefix-sysroot.rs +++ b/tests/ui/errors/remap-path-prefix-sysroot.rs @@ -2,7 +2,7 @@ //@ compile-flags: -g -Ztranslate-remapped-path-to-local-path=yes //@ [with-remap]compile-flags: --remap-path-prefix={{rust-src-base}}=remapped //@ [with-remap]compile-flags: --remap-path-prefix={{src-base}}=remapped-tests-ui -//@ [without-remap]compile-flags: +// [without-remap] no extra compile-flags // The $SRC_DIR*.rs:LL:COL normalisation doesn't kick in automatically // as the remapped revision will not begin with $SRC_DIR_REAL, diff --git a/tests/ui/errors/wrong-target-spec.rs b/tests/ui/errors/wrong-target-spec.rs index a3a0e05d82662..1a9768881122f 100644 --- a/tests/ui/errors/wrong-target-spec.rs +++ b/tests/ui/errors/wrong-target-spec.rs @@ -2,6 +2,7 @@ // checks that such invalid target specs are rejected by the compiler. // See https://github.com/rust-lang/rust/issues/33329 +// ignore-tidy-target-specific-tests //@ needs-llvm-components: x86 //@ compile-flags: --target x86_64_unknown-linux-musl diff --git a/tests/ui/linkage-attr/incompatible-flavor.rs b/tests/ui/linkage-attr/incompatible-flavor.rs index 7f583f47e2f5d..4711343f9c9d6 100644 --- a/tests/ui/linkage-attr/incompatible-flavor.rs +++ b/tests/ui/linkage-attr/incompatible-flavor.rs @@ -1,5 +1,5 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu -C linker-flavor=msvc --crate-type=rlib -//@ needs-llvm-components: +//@ needs-llvm-components: x86 #![feature(no_core)] #![no_core] diff --git a/tests/ui/linkage-attr/unstable-flavor.rs b/tests/ui/linkage-attr/unstable-flavor.rs index 6aa9efb58d1f8..5412e248f341f 100644 --- a/tests/ui/linkage-attr/unstable-flavor.rs +++ b/tests/ui/linkage-attr/unstable-flavor.rs @@ -4,9 +4,9 @@ // //@ revisions: bpf ptx //@ [bpf] compile-flags: --target=bpfel-unknown-none -C linker-flavor=bpf --crate-type=rlib -//@ [bpf] needs-llvm-components: +//@ [bpf] needs-llvm-components: bpf //@ [ptx] compile-flags: --target=nvptx64-nvidia-cuda -C linker-flavor=ptx --crate-type=rlib -//@ [ptx] needs-llvm-components: +//@ [ptx] needs-llvm-components: nvptx #![feature(no_core)] #![no_core] diff --git a/tests/ui/target_modifiers/defaults_check.rs b/tests/ui/target_modifiers/defaults_check.rs index de72acd32bc18..ce1d534fd7573 100644 --- a/tests/ui/target_modifiers/defaults_check.rs +++ b/tests/ui/target_modifiers/defaults_check.rs @@ -6,7 +6,7 @@ //@ needs-llvm-components: x86 //@ revisions: ok ok_explicit error -//@[ok] compile-flags: +// [ok] no extra compile-flags //@[ok_explicit] compile-flags: -Zreg-struct-return=false //@[error] compile-flags: -Zreg-struct-return=true //@[ok] check-pass diff --git a/tests/ui/target_modifiers/incompatible_fixedx18.rs b/tests/ui/target_modifiers/incompatible_fixedx18.rs index 6c13984f608ec..5ba676406ee30 100644 --- a/tests/ui/target_modifiers/incompatible_fixedx18.rs +++ b/tests/ui/target_modifiers/incompatible_fixedx18.rs @@ -5,7 +5,7 @@ //@ revisions:allow_match allow_mismatch error_generated //@[allow_match] compile-flags: -Zfixed-x18 //@[allow_mismatch] compile-flags: -Cunsafe-allow-abi-mismatch=fixed-x18 -//@[error_generated] compile-flags: +// [error_generated] no extra compile-flags //@[allow_mismatch] check-pass //@[allow_match] check-pass diff --git a/tests/ui/target_modifiers/incompatible_regparm.rs b/tests/ui/target_modifiers/incompatible_regparm.rs index 395c26fc2c02d..e76bfc976a193 100644 --- a/tests/ui/target_modifiers/incompatible_regparm.rs +++ b/tests/ui/target_modifiers/incompatible_regparm.rs @@ -5,7 +5,7 @@ //@ revisions:allow_regparm_mismatch allow_no_value error_generated //@[allow_regparm_mismatch] compile-flags: -Cunsafe-allow-abi-mismatch=regparm //@[allow_no_value] compile-flags: -Cunsafe-allow-abi-mismatch -//@[error_generated] compile-flags: +// [error_generated] no extra compile-flags //@[allow_regparm_mismatch] check-pass #![feature(no_core)] diff --git a/tests/ui/target_modifiers/no_value_bool.rs b/tests/ui/target_modifiers/no_value_bool.rs index ceba40afa8968..72130f8737c02 100644 --- a/tests/ui/target_modifiers/no_value_bool.rs +++ b/tests/ui/target_modifiers/no_value_bool.rs @@ -8,7 +8,7 @@ //@ revisions: ok ok_explicit error error_explicit //@[ok] compile-flags: -Zreg-struct-return //@[ok_explicit] compile-flags: -Zreg-struct-return=true -//@[error] compile-flags: +// [error] no extra compile-flags //@[error_explicit] compile-flags: -Zreg-struct-return=false //@[ok] check-pass //@[ok_explicit] check-pass From 730d33dd6476ebe4342da9e14c1079f277e1ee74 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 7 Jul 2025 14:37:50 +0200 Subject: [PATCH 11/13] `loop_match`: suggest extracting to a `const` item if the expression cannot be evaluated in a straightforward way --- compiler/rustc_mir_build/messages.ftl | 8 +- compiler/rustc_mir_build/src/builder/scope.rs | 29 ++- compiler/rustc_mir_build/src/errors.rs | 32 ++++ tests/ui/loop-match/suggest-const-item.rs | 174 ++++++++++++++++++ tests/ui/loop-match/suggest-const-item.stderr | 58 ++++++ 5 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 tests/ui/loop-match/suggest-const-item.rs create mode 100644 tests/ui/loop-match/suggest-const-item.stderr diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index e339520cd86b8..abfe8eb66dda8 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -86,10 +86,16 @@ mir_build_confused = missing patterns are not covered because `{$variable}` is i mir_build_const_continue_bad_const = could not determine the target branch for this `#[const_continue]` .label = this value is too generic - .note = the value must be a literal or a monomorphic const mir_build_const_continue_missing_value = a `#[const_continue]` must break to a label with a value +mir_build_const_continue_not_const = could not determine the target branch for this `#[const_continue]` + .help = try extracting the expression into a `const` item + +mir_build_const_continue_not_const_const_block = `const` blocks may use generics, and are not evaluated early enough +mir_build_const_continue_not_const_const_other = this value must be a literal or a monomorphic const +mir_build_const_continue_not_const_constant_parameter = constant parameters may use generics, and are not evaluated early enough + mir_build_const_continue_unknown_jump_target = the target of this `#[const_continue]` is not statically known .label = this value must be a literal or a monomorphic const diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 12a56d7c5ea4c..1240b34cf9d43 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -100,7 +100,9 @@ use tracing::{debug, instrument}; use super::matches::BuiltMatchTree; use crate::builder::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::errors::{ConstContinueBadConst, ConstContinueUnknownJumpTarget}; +use crate::errors::{ + ConstContinueBadConst, ConstContinueNotMonomorphicConst, ConstContinueUnknownJumpTarget, +}; #[derive(Debug)] pub(crate) struct Scopes<'tcx> { @@ -867,7 +869,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span_bug!(span, "break value must be a scope") }; - let constant = match &self.thir[value].kind { + let expr = &self.thir[value]; + let constant = match &expr.kind { ExprKind::Adt(box AdtExpr { variant_index, fields, base, .. }) => { assert!(matches!(base, AdtExprBase::None)); assert!(fields.is_empty()); @@ -887,7 +890,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ), } } - _ => self.as_constant(&self.thir[value]), + + ExprKind::Literal { .. } + | ExprKind::NonHirLiteral { .. } + | ExprKind::ZstLiteral { .. } + | ExprKind::NamedConst { .. } => self.as_constant(&self.thir[value]), + + other => { + use crate::errors::ConstContinueNotMonomorphicConstReason as Reason; + + let span = expr.span; + let reason = match other { + ExprKind::ConstParam { .. } => Reason::ConstantParameter { span }, + ExprKind::ConstBlock { .. } => Reason::ConstBlock { span }, + _ => Reason::Other { span }, + }; + + self.tcx + .dcx() + .emit_err(ConstContinueNotMonomorphicConst { span: expr.span, reason }); + return block.unit(); + } }; let break_index = self diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 16b49bf384c52..f1fbd5c4a4994 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -1213,6 +1213,38 @@ pub(crate) struct LoopMatchArmWithGuard { pub span: Span, } +#[derive(Diagnostic)] +#[diag(mir_build_const_continue_not_const)] +#[help] +pub(crate) struct ConstContinueNotMonomorphicConst { + #[primary_span] + pub span: Span, + + #[subdiagnostic] + pub reason: ConstContinueNotMonomorphicConstReason, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ConstContinueNotMonomorphicConstReason { + #[label(mir_build_const_continue_not_const_constant_parameter)] + ConstantParameter { + #[primary_span] + span: Span, + }, + + #[label(mir_build_const_continue_not_const_const_block)] + ConstBlock { + #[primary_span] + span: Span, + }, + + #[label(mir_build_const_continue_not_const_const_other)] + Other { + #[primary_span] + span: Span, + }, +} + #[derive(Diagnostic)] #[diag(mir_build_const_continue_bad_const)] pub(crate) struct ConstContinueBadConst { diff --git a/tests/ui/loop-match/suggest-const-item.rs b/tests/ui/loop-match/suggest-const-item.rs new file mode 100644 index 0000000000000..f921b430b8c9f --- /dev/null +++ b/tests/ui/loop-match/suggest-const-item.rs @@ -0,0 +1,174 @@ +#![allow(incomplete_features)] +#![feature(loop_match)] +#![feature(generic_const_items)] +#![crate_type = "lib"] + +const fn const_fn() -> i32 { + 1 +} + +#[unsafe(no_mangle)] +fn suggest_const_block() -> i32 { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk const_fn(); + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + 1 => { + #[const_continue] + break 'blk const { const_fn() }; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + 2 => { + #[const_continue] + break 'blk N; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => { + #[const_continue] + break 'blk 1 + 1; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + } + } + } + state +} + +struct S; + +impl S { + const M: usize = 42; + + fn g() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk Self::M; + } + _ => panic!(), + } + } + } + } +} + +trait T { + const N: usize; + + fn f() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk Self::N; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => panic!(), + } + } + } + } +} + +impl T for S { + const N: usize = 1; +} + +impl S { + fn h() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk Self::N; + } + _ => panic!(), + } + } + } + } +} + +trait T2 { + const L: u32; + + fn p() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk Self::L; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => panic!(), + } + } + } + } +} + +const SIZE_OF: usize = size_of::(); + +fn q() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk SIZE_OF::; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => panic!(), + } + } + } +} + +trait Trait { + const X: usize = 9000; + const Y: usize = size_of::(); +} + +impl Trait for () {} + +fn r() { + let mut state = 0; + #[loop_match] + loop { + state = 'blk: { + match state { + 0 => { + #[const_continue] + break 'blk <() as Trait>::X; + } + 1 => { + #[const_continue] + break 'blk <() as Trait>::Y; + //~^ ERROR could not determine the target branch for this `#[const_continue]` + } + _ => panic!(), + } + } + } +} diff --git a/tests/ui/loop-match/suggest-const-item.stderr b/tests/ui/loop-match/suggest-const-item.stderr new file mode 100644 index 0000000000000..787474479ad5a --- /dev/null +++ b/tests/ui/loop-match/suggest-const-item.stderr @@ -0,0 +1,58 @@ +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:19:32 + | +LL | break 'blk const_fn(); + | ^^^^^^^^^^ this value must be a literal or a monomorphic const + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:24:32 + | +LL | break 'blk const { const_fn() }; + | ^^^^^^^^^^^^^^^^^^^^ `const` blocks may use generics, and are not evaluated early enough + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:29:32 + | +LL | break 'blk N; + | ^ constant parameters may use generics, and are not evaluated early enough + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:34:32 + | +LL | break 'blk 1 + 1; + | ^^^^^ this value must be a literal or a monomorphic const + | + = help: try extracting the expression into a `const` item + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:76:36 + | +LL | break 'blk Self::N; + | ^^^^^^^ this value is too generic + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:119:36 + | +LL | break 'blk Self::L; + | ^^^^^^^ this value is too generic + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:139:32 + | +LL | break 'blk SIZE_OF::; + | ^^^^^^^^^^^^ this value is too generic + +error: could not determine the target branch for this `#[const_continue]` + --> $DIR/suggest-const-item.rs:167:32 + | +LL | break 'blk <() as Trait>::Y; + | ^^^^^^^^^^^^^^^^^^^ this value is too generic + +error: aborting due to 8 previous errors + From 1f4561b63d1bca64675373385ed8292dcd23e7e6 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 9 May 2025 21:27:18 +0100 Subject: [PATCH 12/13] Don't lint against named labels in `naked_asm!` Naked functions are allowed to define global labels, just like `global_asm!`. --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 11 +++++++- tests/ui/asm/named-asm-labels.rs | 26 +++++++++++++++---- tests/ui/asm/named-asm-labels.stderr | 39 +++++++++++----------------- 4 files changed, 47 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 97e070958751a..984b280e81b5a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2849,7 +2849,7 @@ impl InlineAsmOperand { } } -#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic, Walkable)] +#[derive(Clone, Copy, Encodable, Decodable, Debug, HashStable_Generic, Walkable, PartialEq, Eq)] pub enum AsmMacro { /// The `asm!` macro Asm, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index eb4c3703dbd6f..bf128b5914f0f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2870,7 +2870,7 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels { if let hir::Expr { kind: hir::ExprKind::InlineAsm(hir::InlineAsm { - asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm, + asm_macro: asm_macro @ (AsmMacro::Asm | AsmMacro::NakedAsm), template_strs, options, .. @@ -2878,6 +2878,15 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels { .. } = expr { + // Non-generic naked functions are allowed to define arbitrary + // labels. + if *asm_macro == AsmMacro::NakedAsm { + let def_id = expr.hir_id.owner.def_id; + if !cx.tcx.generics_of(def_id).requires_monomorphization(cx.tcx) { + return; + } + } + // asm with `options(raw)` does not do replacement with `{` and `}`. let raw = options.contains(InlineAsmOptions::RAW); diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs index 996fb82a944f2..e78553fd775f0 100644 --- a/tests/ui/asm/named-asm-labels.rs +++ b/tests/ui/asm/named-asm-labels.rs @@ -171,12 +171,10 @@ fn main() { } } -// Trigger on naked fns too, even though they can't be inlined, reusing a -// label or LTO can cause labels to break +// Don't trigger on naked functions. #[unsafe(naked)] pub extern "C" fn foo() -> i32 { naked_asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1) - //~^ ERROR avoid using named labels } // Make sure that non-naked attributes *do* still let the lint happen @@ -190,7 +188,18 @@ pub extern "C" fn bar() { pub extern "C" fn aaa() { fn _local() {} - naked_asm!(".Laaa: nop; ret;") //~ ERROR avoid using named labels + naked_asm!(".Laaa: nop; ret;") +} + +#[unsafe(naked)] +pub extern "C" fn bbb<'a>(a: &'a u32) { + naked_asm!(".Lbbb: nop; ret;") +} + +#[unsafe(naked)] +pub extern "C" fn ccc(a: &T) { + naked_asm!(".Lccc: nop; ret;") + //~^ ERROR avoid using named labels } pub fn normal() { @@ -200,7 +209,7 @@ pub fn normal() { pub extern "C" fn bbb() { fn _very_local() {} - naked_asm!(".Lbbb: nop; ret;") //~ ERROR avoid using named labels + naked_asm!(".Lbbb: nop; ret;") } fn _local2() {} @@ -230,3 +239,10 @@ fn closures() { // Don't trigger on global asm global_asm!("aaaaaaaa: nop"); + +trait Foo { + #[unsafe(naked)] + extern "C" fn bbb<'a>(a: &'a u32) { + naked_asm!(".Lbbb: nop; ret;") //~ ERROR avoid using named labels + } +} diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr index cd7e7a08c1d29..9ba9e14de3aeb 100644 --- a/tests/ui/asm/named-asm-labels.stderr +++ b/tests/ui/asm/named-asm-labels.stderr @@ -475,16 +475,7 @@ LL | #[warn(named_asm_labels)] | ^^^^^^^^^^^^^^^^ error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:178:17 - | -LL | naked_asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1) - | ^^^^^ - | - = help: only local labels of the form `:` should be used in inline asm - = note: see the asm section of Rust By Example for more information - -error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:185:20 + --> $DIR/named-asm-labels.rs:183:20 | LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) } | ^^^^^ @@ -493,49 +484,49 @@ LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:193:17 + --> $DIR/named-asm-labels.rs:201:17 | -LL | naked_asm!(".Laaa: nop; ret;") +LL | naked_asm!(".Lccc: nop; ret;") | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:203:21 + --> $DIR/named-asm-labels.rs:221:15 | -LL | naked_asm!(".Lbbb: nop; ret;") - | ^^^^^ +LL | asm!("closure1: nop"); + | ^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:212:15 + --> $DIR/named-asm-labels.rs:225:15 | -LL | asm!("closure1: nop"); +LL | asm!("closure2: nop"); | ^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:216:15 + --> $DIR/named-asm-labels.rs:235:19 | -LL | asm!("closure2: nop"); - | ^^^^^^^^ +LL | asm!("closure3: nop"); + | ^^^^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information error: avoid using named labels in inline assembly - --> $DIR/named-asm-labels.rs:226:19 + --> $DIR/named-asm-labels.rs:246:21 | -LL | asm!("closure3: nop"); - | ^^^^^^^^ +LL | naked_asm!(".Lbbb: nop; ret;") + | ^^^^^ | = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information -error: aborting due to 56 previous errors; 1 warning emitted +error: aborting due to 55 previous errors; 1 warning emitted From 53018dc2bcd0f0ee65ca9c869130ec0e56da63e2 Mon Sep 17 00:00:00 2001 From: Jens Reidel Date: Fri, 25 Jul 2025 01:45:42 +0000 Subject: [PATCH 13/13] Disable has_reliable_f128_math on musl targets musl does not implement the symbols required by std for f128 maths. Disable the associated cfg for all musl targets and adjust the tests accordingly. Signed-off-by: Jens Reidel --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 3 +++ tests/ui/float/target-has-reliable-nightly-float.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 0fb987bdf82ed..8edbae115bf50 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -433,6 +433,9 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) { // This rules out anything that doesn't have `long double` = `binary128`; <= 32 bits // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86` // (ld is 80-bit extended precision). + // + // musl does not implement the symbols required for f128 math at all. + _ if target_env == "musl" => false, ("x86_64", _) => false, (_, "linux") if target_pointer_width == 64 => true, _ => false, diff --git a/tests/ui/float/target-has-reliable-nightly-float.rs b/tests/ui/float/target-has-reliable-nightly-float.rs index ad8600fc63593..399f101f49ae2 100644 --- a/tests/ui/float/target-has-reliable-nightly-float.rs +++ b/tests/ui/float/target-has-reliable-nightly-float.rs @@ -19,8 +19,10 @@ pub fn has_f128() {} pub fn has_f128_math() {} fn main() { - if cfg!(target_arch = "aarch64") && cfg!(target_os = "linux") { - // Aarch64+Linux is one target that has support for all features, so use it to spot + if cfg!(target_arch = "aarch64") && + cfg!(target_os = "linux") && + cfg!(not(target_env = "musl")) { + // Aarch64+GNU+Linux is one target that has support for all features, so use it to spot // check that the compiler does indeed enable these gates. assert!(cfg!(target_has_reliable_f16));