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 b8d628c1e12c51c9adf4fecf1aadd74e11c48d76 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 21 Jul 2025 20:13:35 -0500 Subject: [PATCH 07/13] Use LocalKey methods more --- compiler/rustc_errors/src/markdown/term.rs | 8 ++++---- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +++--- compiler/rustc_query_system/src/query/plumbing.rs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/markdown/term.rs b/compiler/rustc_errors/src/markdown/term.rs index 579e00b8b85bd..fe1d80bdbe8e0 100644 --- a/compiler/rustc_errors/src/markdown/term.rs +++ b/compiler/rustc_errors/src/markdown/term.rs @@ -18,7 +18,7 @@ thread_local! { pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Buffer) -> io::Result<()> { #[cfg(not(test))] if let Some((w, _)) = termize::dimensions() { - WIDTH.with(|c| c.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH))); + WIDTH.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH)); } write_stream(stream, buf, None, 0)?; buf.write_all(b"\n") @@ -84,7 +84,7 @@ fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> reset_cursor(); } MdTree::HorizontalRule => { - (0..WIDTH.with(Cell::get)).for_each(|_| buf.write_all(b"-").unwrap()); + (0..WIDTH.get()).for_each(|_| buf.write_all(b"-").unwrap()); reset_cursor(); } MdTree::Heading(n, stream) => { @@ -121,7 +121,7 @@ fn write_tt(tt: &MdTree<'_>, buf: &mut Buffer, indent: usize) -> io::Result<()> /// End of that block, just wrap the line fn reset_cursor() { - CURSOR.with(|cur| cur.set(0)); + CURSOR.set(0); } /// Change to be generic on Write for testing. If we have a link URL, we don't @@ -144,7 +144,7 @@ fn write_wrapping( buf.write_all(ind_ws)?; cur.set(indent); } - let ch_count = WIDTH.with(Cell::get) - cur.get(); + let ch_count = WIDTH.get() - cur.get(); let mut iter = to_write.char_indices(); let Some((end_idx, _ch)) = iter.nth(ch_count) else { // Write entire line diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 9ee64df0ad065..fd4472e1f9658 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -86,7 +86,7 @@ macro_rules! define_helper { impl $helper { pub fn new() -> $helper { - $helper($tl.with(|c| c.replace(true))) + $helper($tl.replace(true)) } } @@ -100,12 +100,12 @@ macro_rules! define_helper { impl Drop for $helper { fn drop(&mut self) { - $tl.with(|c| c.set(self.0)) + $tl.set(self.0) } } pub fn $name() -> bool { - $tl.with(|c| c.get()) + $tl.get() } )+ } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 06e59eb4cccde..e74de5edc42d7 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -720,7 +720,7 @@ fn incremental_verify_ich_failed( static INSIDE_VERIFY_PANIC: Cell = const { Cell::new(false) }; }; - let old_in_panic = INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.replace(true)); + let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); if old_in_panic { tcx.sess().dcx().emit_err(crate::error::Reentrant); @@ -739,7 +739,7 @@ fn incremental_verify_ich_failed( panic!("Found unstable fingerprints for {dep_node:?}: {}", result()); } - INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic)); + INSIDE_VERIFY_PANIC.set(old_in_panic); } /// Ensure that either this query has all green inputs or been executed. From e958b20af7ad3e3a053070a9c45389fe463ccc0c Mon Sep 17 00:00:00 2001 From: Ben Schulz Date: Wed, 9 Jul 2025 18:46:11 +0200 Subject: [PATCH 08/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 09/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 10/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 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));