From 0f19b6d173b989c3b091f30522b56cb8b0a32497 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Wed, 15 Apr 2026 17:47:15 +0000 Subject: [PATCH 1/8] Fix pathological performance in trait solver cycles with errors Fuchsia's Starnix system has had a multi-year long bug where occasionally a typo could cause the rust compiler to take 10+ hours to report an error. This was particularly hard to trace down since Starnix's codebase is massive, over 384 thousand lines as of writing. With the help of treereduce, cargo-minimize, and rustmerge, after about a month of running we reduced it down to a couple [lines of code], which only takes about 35 seconds to report an error on my machine. The bug also appears to happen with `-Z next-solver=no` and `-Z next-solver=coherence`, but does not occur with `-Z next-solver` or `-Z next-solver=globally`. I used Gemini to help diagnose the problem and proposed solution (which is the one proposed in this patch): 1. The trait solver gets stuck in an exponential loop evaluating auto-trait bounds (like Send and Sync) on cyclic types that contain compilation errors (TyKind::Error). 2. Normally, if the solver detects a cycle, it prevents the result from being stored in the Global Cache because the result depends on the current evaluation stack. However, when an error is involved, the depth tracking gets pinned to a low value, forcing the solver to rely on the short-lived Provisional Cache. Since the provisional cache is cleared between high-level iterations of the fulfillment loop, the solver ends up re-discovering and re-evaluating the same large cycle thousands of times. 3. Allow global caching of results even if they appear stack-dependent, provided that the inference context is already "tainted by errors" (`self.infcx.tainted_by_errors().is_some()`). This violates the strict invariant that global cache entries shouldn't depend on the stack, but it is safe because the compilation is already guaranteed to fail due to the presence of errors. Prioritizing compiler responsiveness and termination over perfect correctness in error states is the correct trade-off here. I added the reduction as the test case for this. However, I don't see an easy way to catch if this bug comes back. Should we add some way to timeout the test if it takes longer than 10 seconds to compile? That could be a source of flakes though. I don't have any experience with the trait solver code, but I did try to review the code to the best of my ability. This approach seems a bit of a bandaid to the solution, but I don't see a better solution. We could try to teach the solver to not clear the provisional cache in this circumstance, but I suspect that'd be a pretty invasive change. I'm guessing if this does cause problems, it might report an incorrect error, but I (and Gemini) were unable to come up with an example that reported a different error with and without this fix. [lines of code]: https://gist.github.com/erickt/255bc4006292cac88de906bd6bd9220a --- .../src/traits/select/mod.rs | 8 ++ tests/ui/traits/cycle-cache-err-150907.rs | 125 ++++++++++++++++++ tests/ui/traits/cycle-cache-err-150907.stderr | 14 ++ 3 files changed, 147 insertions(+) create mode 100644 tests/ui/traits/cycle-cache-err-150907.rs create mode 100644 tests/ui/traits/cycle-cache-err-150907.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a564e8060d930..205e04cc5d2c4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1113,6 +1113,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("CACHE MISS"); self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); stack.cache().on_completion(stack.dfn); + } else if let Some(_guar) = self.infcx.tainted_by_errors() { + // When an error has occurred, we allow global caching of results even if they + // appear stack-dependent. This prevents exponential re-evaluation of cycles + // in the presence of errors, avoiding compiler hangs like #150907. + // This is safe because compilation will fail anyway. + debug!("CACHE MISS (tainted by errors)"); + self.insert_evaluation_cache(param_env, fresh_trait_pred, dep_node, result); + stack.cache().on_completion(stack.dfn); } else { debug!("PROVISIONAL"); debug!( diff --git a/tests/ui/traits/cycle-cache-err-150907.rs b/tests/ui/traits/cycle-cache-err-150907.rs new file mode 100644 index 0000000000000..86bceab442ffc --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-150907.rs @@ -0,0 +1,125 @@ +// Test that we don't hang or take exponential time when evaluating +// auto-traits for cyclic types containing errors, based on the reproducer +// provided in issue #150907. + +use std::sync::Arc; +use std::marker::PhantomData; + +struct Weak(PhantomData); +unsafe impl Send for Weak {} +unsafe impl Sync for Weak {} + +struct BTreeMap(K, V); + +trait DeviceOps: Send {} + +struct SerialDevice { + terminal: Weak, +} + +impl DeviceOps for SerialDevice {} + +struct TtyState { + terminals: Weak, +} + +struct TerminalMutableState { + controller: TerminalController, +} + +struct Terminal { + weak_self: Weak, + state: Arc, + mutable_state: Weak, +} + +struct TerminalController { + session: Weak, +} + +struct Kernel { + weak_self: Weak, + kthreads: KernelThreads, + pids: Weak, +} + +struct KernelThreads { + system_task: SystemTask, + kernel: Weak, +} + +struct SystemTask { + system_thread_group: Weak, +} + +enum ProcessEntry { + ThreadGroup(Weak), +} + +struct PidEntry { + task: Arc, + process: ProcessEntry, +} + +struct PidTable { + table: PidEntry, + process_groups: Arc, +} + +struct ProcessGroupMutableState { + thread_groups: Weak, +} + +struct ProcessGroup { + session: Arc, + mutable_state: Arc, +} + +struct SessionMutableState { + process_groups: BTreeMap<(), Weak>, + controlling_terminal: ControllingTerminal, +} + +struct Session { + mutable_state: Weak, +} + +struct ControllingTerminal { + terminal: Arc, +} + +struct TaskPersistentInfoState { + thread_group_key: ThreadGroupKey, +} + +struct Task { + thread_group_key: ThreadGroupKey, + kernel: Arc, + thread_group: Arc, + persistent_info: Arc, + vfork_event: Arc, //~ ERROR missing generics for struct `Arc` +} + +struct ThreadGroupKey { + thread_group: Arc, +} + +struct ThreadGroupMutableState { + tasks: BTreeMap<(), TaskContainer>, + children: BTreeMap<(), Weak>, + process_group: Arc, +} + +struct ThreadGroup { + kernel: Arc, + mutable_state: Weak, +} + +struct TaskContainer(Arc, Arc); + +fn main() { + // Trigger auto-trait check for one of the cyclic types + is_send::(); +} + +fn is_send() {} diff --git a/tests/ui/traits/cycle-cache-err-150907.stderr b/tests/ui/traits/cycle-cache-err-150907.stderr new file mode 100644 index 0000000000000..a8d680af55377 --- /dev/null +++ b/tests/ui/traits/cycle-cache-err-150907.stderr @@ -0,0 +1,14 @@ +error[E0107]: missing generics for struct `Arc` + --> $DIR/cycle-cache-err-150907.rs:100:18 + | +LL | vfork_event: Arc, + | ^^^ expected at least 1 generic argument + | +help: add missing generic argument + | +LL | vfork_event: Arc, + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0107`. From cafe02e1e353c1ddb72b4981d3beb97d4f99eba3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 27 Apr 2026 09:47:23 +0200 Subject: [PATCH 2/8] Add `first_span` to doc attribute --- compiler/rustc_attr_parsing/src/attributes/doc.rs | 3 +++ compiler/rustc_hir/src/attrs/data_structures.rs | 4 ++++ compiler/rustc_passes/src/check_attr.rs | 1 + src/librustdoc/clean/mod.rs | 1 + src/librustdoc/json/conversions.rs | 1 + 5 files changed, 10 insertions(+) diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 5d07478b152ee..60f469990d51a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -701,6 +701,9 @@ impl DocParser { for i in items.mixed() { match i { MetaItemOrLitParser::MetaItemParser(mip) => { + if self.nb_doc_attrs == 0 { + self.attribute.first_span = cx.attr_span; + } self.nb_doc_attrs += 1; self.parse_single_doc_attr_item(cx, mip); } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 6304b830f6ed7..bab86a25e3cbb 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -544,6 +544,8 @@ pub struct CfgHideShow { #[derive(Clone, Debug, Default, HashStable_Generic, Decodable, PrintAttribute)] pub struct DocAttribute { + pub first_span: Span, + pub aliases: FxIndexMap, pub hidden: Option, // Because we need to emit the error if there is more than one `inline` attribute on an item @@ -581,6 +583,7 @@ pub struct DocAttribute { impl rustc_serialize::Encodable for DocAttribute { fn encode(&self, encoder: &mut E) { let DocAttribute { + first_span, aliases, hidden, inline, @@ -603,6 +606,7 @@ impl rustc_serialize::Encodable for DocAttribute test_attrs, no_crate_inject, } = self; + rustc_serialize::Encodable::::encode(first_span, encoder); rustc_serialize::Encodable::::encode(aliases, encoder); rustc_serialize::Encodable::::encode(hidden, encoder); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ebf0f06f7173d..34c2ec54e8fc9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1027,6 +1027,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// [`check_doc_inline`]: Self::check_doc_inline fn check_doc_attrs(&self, attr: &DocAttribute, hir_id: HirId, target: Target) { let DocAttribute { + first_span: _, aliases, // valid pretty much anywhere, not checked here? // FIXME: should we? diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 81e348f96e569..3f604c1b7bb8b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2780,6 +2780,7 @@ fn add_without_unwanted_attributes<'hir>( hir::Attribute::Parsed(AttributeKind::Doc(box d)) => { // Remove attributes from `normal` that should not be inherited by `use` re-export. let DocAttribute { + first_span: _, aliases, hidden, inline, diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 5d1f4778f1c52..44749fd4c0ec6 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -960,6 +960,7 @@ fn maybe_from_hir_attr(attr: &hir::Attribute, item_id: ItemId, tcx: TyCtxt<'_>) } let DocAttribute { + first_span: _, aliases, hidden, inline, From 71ef1fafe02bd7b62bbdbecf050977d037c90eb3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 27 Apr 2026 09:48:51 +0200 Subject: [PATCH 3/8] Rewrite `check_invalid_where_predicate_attrs` --- .../rustc_attr_parsing/src/target_checking.rs | 17 +++++----- tests/ui/attributes/where-doc.rs | 21 ++++++++++++ tests/ui/attributes/where-doc.stderr | 32 +++++++++++++++++++ 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 tests/ui/attributes/where-doc.rs create mode 100644 tests/ui/attributes/where-doc.stderr diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 65e716921f5cb..8c41d7732c7d5 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -292,15 +292,16 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // in where clauses. After that, this function would become useless. let spans = attrs .into_iter() - // FIXME: We shouldn't need to special-case `doc`! - .filter(|attr| { - matches!( - attr, - Attribute::Parsed(AttributeKind::DocComment { .. } | AttributeKind::Doc(_)) - | Attribute::Unparsed(_) - ) + .filter_map(|attr| { + match attr { + Attribute::Parsed(AttributeKind::DocComment { span, .. }) => Some(*span), + // FIXME: We shouldn't need to special-case `doc`! + Attribute::Parsed(AttributeKind::Doc(attr)) => Some(attr.first_span), + // Checked during attribute parsing target checking + Attribute::Parsed(_) => None, + Attribute::Unparsed(attr) => Some(attr.span), + } }) - .map(|attr| attr.span()) .collect::>(); if !spans.is_empty() { self.dcx() diff --git a/tests/ui/attributes/where-doc.rs b/tests/ui/attributes/where-doc.rs new file mode 100644 index 0000000000000..12fcc71484cb4 --- /dev/null +++ b/tests/ui/attributes/where-doc.rs @@ -0,0 +1,21 @@ +#![feature(where_clause_attrs)] +#![allow(invalid_doc_attributes)] + +fn test() +where +#[doc(alias = ":(")] +//~^ ERROR most attributes are not supported in `where` clauses +//~| ERROR `#[doc(alias = "...")]` isn't allowed on where predicate +():, + +#[doc(hidden)] +//~^ ERROR most attributes are not supported in `where` clauses +():, + +#[doc = ""] +//~^ ERROR most attributes are not supported in `where` clauses +():, + +{ } + +fn main() {} diff --git a/tests/ui/attributes/where-doc.stderr b/tests/ui/attributes/where-doc.stderr new file mode 100644 index 0000000000000..c8efaaeedfaac --- /dev/null +++ b/tests/ui/attributes/where-doc.stderr @@ -0,0 +1,32 @@ +error: most attributes are not supported in `where` clauses + --> $DIR/where-doc.rs:6:1 + | +LL | #[doc(alias = ":(")] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` and `#[cfg_attr]` are supported + +error: most attributes are not supported in `where` clauses + --> $DIR/where-doc.rs:11:1 + | +LL | #[doc(hidden)] + | ^^^^^^^^^^^^^^ + | + = help: only `#[cfg]` and `#[cfg_attr]` are supported + +error: most attributes are not supported in `where` clauses + --> $DIR/where-doc.rs:15:1 + | +LL | #[doc = ""] + | ^^^^^^^^^^^ + | + = help: only `#[cfg]` and `#[cfg_attr]` are supported + +error: `#[doc(alias = "...")]` isn't allowed on where predicate + --> $DIR/where-doc.rs:6:15 + | +LL | #[doc(alias = ":(")] + | ^^^^ + +error: aborting due to 4 previous errors + From 75fa098069941f0aa4223ead622528cb2ce4982c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 27 Apr 2026 09:52:43 +0200 Subject: [PATCH 4/8] Add test for existing bug --- tests/ui/attributes/where-doc.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/ui/attributes/where-doc.rs b/tests/ui/attributes/where-doc.rs index 12fcc71484cb4..761d83966f659 100644 --- a/tests/ui/attributes/where-doc.rs +++ b/tests/ui/attributes/where-doc.rs @@ -16,6 +16,19 @@ where //~^ ERROR most attributes are not supported in `where` clauses ():, +// == That the doc attributes below don't trigger the error is a bug +#[doc()] +():, + +#[doc(5)] +():, + +#[doc] +():, + +#[doc = 5] +():, + { } fn main() {} From 23abf90ff8a0ad5aeae6ea5f344338ab9af97485 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 27 Apr 2026 10:05:57 +0200 Subject: [PATCH 5/8] add test --- .../is-global-norm-binius_field-regression.rs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-binius_field-regression.rs diff --git a/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-binius_field-regression.rs b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-binius_field-regression.rs new file mode 100644 index 0000000000000..bcf3867b65f7c --- /dev/null +++ b/tests/ui/traits/next-solver/normalization-shadowing/is-global-norm-binius_field-regression.rs @@ -0,0 +1,51 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// One of the minimizations from trait-system-refactor-initiative#257 which ended up +// getting fixed by #153614. It seems somewhat likely that this is somewhat +// accidental by changing the exact shape of the cycle, causing us to avoid the +// underlying issue of trait-system-refactor-initiative#257. + +pub trait Field: Sized + HasUnderlier> {} +pub trait PackScalar: 'static + UnderlierType { + type Packed; +} +trait PackedField { + type Scalar; +} +pub trait UnderlierType {} +pub trait HasUnderlier { + type Underlier; +} +impl HasUnderlier for U { + type Underlier = U; +} +impl UnderlierType for u8 {} +struct MyField; +impl Field for MyField {} +impl HasUnderlier for MyField { + type Underlier = u8; +} +impl PackScalar for u8 +where + F: Field, +{ + type Packed = PackedPrimitiveType; +} +pub struct PackedPrimitiveType(Scalar); +impl PackedField for PackedPrimitiveType +where + Scalar: Field, +{ + type Scalar = Scalar; +} + +pub trait PackedTransformationFactory {} +trait TaggedPackedTransformationFactory: PackedField {} +impl PackedTransformationFactory for PackedPrimitiveType where + Self: TaggedPackedTransformationFactory +{ +} +fn main() {} From 44617ef8dba7590fd2cd7224c479834e723f249d Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 Apr 2026 10:25:20 +0200 Subject: [PATCH 6/8] Render `ConstContext` for diagnostics once instead of duplicating in every diagnostic --- compiler/rustc_const_eval/src/errors.rs | 138 ++++-------------------- compiler/rustc_hir/src/hir.rs | 4 +- 2 files changed, 20 insertions(+), 122 deletions(-) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index a61601a7b3c86..311696a3acc99 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -139,14 +139,7 @@ pub(crate) struct PanicNonStrErr { } #[derive(Diagnostic)] -#[diag( - r#"function pointer calls are not allowed in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# -)] +#[diag(r#"function pointer calls are not allowed in {$kind}s"#)] pub(crate) struct UnallowedFnPointerCall { #[primary_span] pub span: Span, @@ -224,12 +217,7 @@ pub(crate) struct MutableBorrowEscaping { #[derive(Diagnostic)] #[diag( - r#"cannot call {$non_or_conditionally}-const formatting macro in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, + r#"cannot call {$non_or_conditionally}-const formatting macro in {$kind}s"#, code = E0015, )] pub(crate) struct NonConstFmtMacroCall { @@ -240,12 +228,7 @@ pub(crate) struct NonConstFmtMacroCall { } #[derive(Diagnostic)] -#[diag(r#"cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const {$def_descr} `{$def_path_str}` in {$kind}s"#, code = E0015)] pub(crate) struct NonConstFnCall { #[primary_span] pub span: Span, @@ -256,14 +239,7 @@ pub(crate) struct NonConstFnCall { } #[derive(Diagnostic)] -#[diag( - r#"cannot call non-const intrinsic `{$name}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# -)] +#[diag(r#"cannot call non-const intrinsic `{$name}` in {$kind}s"#)] pub(crate) struct NonConstIntrinsic { #[primary_span] pub span: Span, @@ -280,12 +256,7 @@ pub(crate) struct UnallowedOpInConstContext { } #[derive(Diagnostic)] -#[diag(r#"inline assembly is not allowed in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"inline assembly is not allowed in {$kind}s"#, code = E0015)] pub(crate) struct UnallowedInlineAsm { #[primary_span] pub span: Span, @@ -384,14 +355,7 @@ pub(crate) struct RawBytesNote { } #[derive(Diagnostic)] -#[diag( - r#"cannot match on `{$ty}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# -)] +#[diag(r#"cannot match on `{$ty}` in {$kind}s"#)] #[note("`{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es")] pub(crate) struct NonConstMatchEq<'tcx> { #[primary_span] @@ -402,12 +366,7 @@ pub(crate) struct NonConstMatchEq<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"cannot use `for` loop on `{$ty}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot use `for` loop on `{$ty}` in {$kind}s"#, code = E0015)] pub(crate) struct NonConstForLoopIntoIter<'tcx> { #[primary_span] pub span: Span, @@ -417,12 +376,7 @@ pub(crate) struct NonConstForLoopIntoIter<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind}s"#, code = E0015)] pub(crate) struct NonConstQuestionBranch<'tcx> { #[primary_span] pub span: Span, @@ -432,12 +386,7 @@ pub(crate) struct NonConstQuestionBranch<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"`?` is not allowed on `{$ty}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"`?` is not allowed on `{$ty}` in {$kind}s"#, code = E0015)] pub(crate) struct NonConstQuestionFromResidual<'tcx> { #[primary_span] pub span: Span, @@ -447,12 +396,7 @@ pub(crate) struct NonConstQuestionFromResidual<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"`try` block cannot convert `{$ty}` to the result in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"`try` block cannot convert `{$ty}` to the result in {$kind}s"#, code = E0015)] pub(crate) struct NonConstTryBlockFromOutput<'tcx> { #[primary_span] pub span: Span, @@ -462,12 +406,7 @@ pub(crate) struct NonConstTryBlockFromOutput<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"cannot convert `{$ty}` into a future in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot convert `{$ty}` into a future in {$kind}s"#, code = E0015)] pub(crate) struct NonConstAwait<'tcx> { #[primary_span] pub span: Span, @@ -477,12 +416,7 @@ pub(crate) struct NonConstAwait<'tcx> { } #[derive(Diagnostic)] -#[diag(r#"cannot call {$non_or_conditionally}-const closure in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const closure in {$kind}s"#, code = E0015)] pub(crate) struct NonConstClosure { #[primary_span] pub span: Span, @@ -493,12 +427,7 @@ pub(crate) struct NonConstClosure { } #[derive(Diagnostic)] -#[diag(r#"calling const c-variadic functions is unstable in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"calling const c-variadic functions is unstable in {$kind}s"#, code = E0015)] pub(crate) struct NonConstCVariadicCall { #[primary_span] pub span: Span, @@ -512,23 +441,9 @@ pub(crate) enum NonConstClosureNote { #[primary_span] span: Span, }, - #[note( - r#"function pointers need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} - }s"# - )] + #[note(r#"function pointers need an RFC before allowed to be called in {$kind}s"#)] FnPtr { kind: ConstContext }, - #[note( - r#"closures need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} - }s"# - )] + #[note(r#"closures need an RFC before allowed to be called in {$kind}s"#)] Closure { kind: ConstContext }, } @@ -543,12 +458,7 @@ pub(crate) struct ConsiderDereferencing { } #[derive(Diagnostic)] -#[diag(r#"cannot call {$non_or_conditionally}-const operator in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot call {$non_or_conditionally}-const operator in {$kind}s"#, code = E0015)] pub(crate) struct NonConstOperator { #[primary_span] pub span: Span, @@ -559,12 +469,7 @@ pub(crate) struct NonConstOperator { } #[derive(Diagnostic)] -#[diag(r#"cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"#, code = E0015)] +#[diag(r#"cannot perform {$non_or_conditionally}-const deref coercion on `{$ty}` in {$kind}s"#, code = E0015)] #[note("attempting to deref into `{$target_ty}`")] pub(crate) struct NonConstDerefCoercion<'tcx> { #[primary_span] @@ -581,14 +486,7 @@ pub(crate) struct NonConstDerefCoercion<'tcx> { #[diag("destructor of `{$dropped_ty}` cannot be evaluated at compile-time", code = E0493)] pub(crate) struct LiveDrop<'tcx> { #[primary_span] - #[label( - r#"the destructor for this type cannot be evaluated in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} - }s"# - )] + #[label(r#"the destructor for this type cannot be evaluated in {$kind}s"#)] pub span: Span, pub kind: ConstContext, pub dropped_ty: Ty<'tcx>, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d8e675c6c56b4..f99125d90821d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2389,9 +2389,9 @@ impl fmt::Display for ConstContext { impl IntoDiagArg for ConstContext { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(match self { - ConstContext::ConstFn => "const_fn", + ConstContext::ConstFn => "constant function", ConstContext::Static(_) => "static", - ConstContext::Const { .. } => "const", + ConstContext::Const { .. } => "constant", })) } } From 8c029d5f456775294204a8c28b24d6ba19865d79 Mon Sep 17 00:00:00 2001 From: cypherair <262752927+cypherair@users.noreply.github.com> Date: Sat, 25 Apr 2026 15:46:42 -0700 Subject: [PATCH 7/8] arm64e: set ptrauth ABI subtype on rmeta Mach-O objects Rust packs rlib metadata into a lib.rmeta archive member encoded as a Mach-O object. For Apple arm64e, extend the existing metadata-object subtype special case from bare CPU_SUBTYPE_ARM64E to CPU_SUBTYPE_ARM64E | CPU_SUBTYPE_PTRAUTH_ABI. --- compiler/rustc_codegen_ssa/src/back/metadata.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index cb66dabf507a5..f3e28484bf11d 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -216,7 +216,9 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Date: Fri, 27 Mar 2026 13:41:52 +0000 Subject: [PATCH 8/8] triagebot: Mention 'subtree' in triagebot message for all subtrees --- triagebot.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 86192295e0cdb..88dc57021b968 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -940,9 +940,11 @@ message = "`triagebot.toml` has been modified, there may have been changes to th cc = ["@davidtwco", "@wesleywiser"] [mentions."compiler/rustc_codegen_cranelift"] +message = "The Cranelift subtree was changed" cc = ["@bjorn3"] [mentions."compiler/rustc_codegen_gcc"] +message = "The GCC codegen subtree was changed" cc = ["@antoyo", "@GuillaumeGomez"] [mentions."compiler/rustc_const_eval/src/"] @@ -1140,6 +1142,7 @@ cc = [ cc = ["@ehuss"] [mentions."src/tools/clippy"] +message = "The Clippy subtree was changed" cc = ["@rust-lang/clippy"] [mentions."src/tools/compiletest"] @@ -1169,6 +1172,7 @@ this change to [rust-lang/rust-analyzer] instead. cc = ["@rust-lang/rust-analyzer"] [mentions."src/tools/rustfmt"] +message = "The Rustfmt subtree was changed" cc = ["@rust-lang/rustfmt"] [mentions."compiler/rustc_middle/src/mir/syntax.rs"]