From 4d07a8f24c42c4cb7362ea8c4db8cfca62a846b2 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 8 Feb 2026 12:29:59 -0500 Subject: [PATCH 1/4] std: Don't panic when removing a nonexistent UEFI var `std::env::remove_var` does not say that deleting a nonexistent variable is an error (and at least on Linux, it indeed does not cause an error). The UEFI Shell Protocol spec also doesn't say it's an error, but the edk2 implementation delegates to the UEFI runtime `SetVariable` function, which returns `EFI_NOT_FOUND` when trying to delete a nonexistent variable. Change the UEFI implementation to check for a `NotFound` error and treat it as success. --- library/std/src/sys/env/uefi.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/env/uefi.rs b/library/std/src/sys/env/uefi.rs index af16a02642a4c..bc2aed4231797 100644 --- a/library/std/src/sys/env/uefi.rs +++ b/library/std/src/sys/env/uefi.rs @@ -43,7 +43,20 @@ mod uefi_env { pub(crate) fn unset(key: &OsStr) -> io::Result<()> { let mut key_ptr = helpers::os_string_to_raw(key) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; - unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } + let r = unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }; + + // The UEFI Shell spec only lists `EFI_SUCCESS` as a possible return value for + // `SetEnv`, but the edk2 implementation can return errors. Allow most of these + // errors to bubble up to the caller, but ignore `NotFound` errors; deleting a + // nonexistent variable is not listed as an error condition of + // `std::env::remove_var`. + if let Err(err) = &r + && err.kind() == io::ErrorKind::NotFound + { + Ok(()) + } else { + r + } } pub(crate) fn get_all() -> io::Result> { From 2d65a33c612cf85e9a0b80e73c870520eb289008 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 00:01:35 +0100 Subject: [PATCH 2/4] Implement indent check --- .../src/diagnostics/diagnostic_builder.rs | 7 +++- .../rustc_macros/src/diagnostics/message.rs | 39 +++++++++++++++++-- .../rustc_macros/src/diagnostics/utils.rs | 2 +- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index b386408a19186..de8ee42caf45c 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -203,8 +203,11 @@ impl DiagnosticDeriveVariantBuilder { ) .emit(); } - self.message = - Some(Message { message_span: message.span(), value: message.value() }); + self.message = Some(Message { + attr_span: attr.span(), + message_span: message.span(), + value: message.value(), + }); } // Parse arguments diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 18d4d60dde3ee..3276abfce4132 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -9,6 +9,7 @@ use crate::diagnostics::error::span_err; #[derive(Clone)] pub(crate) struct Message { + pub attr_span: Span, pub message_span: Span, pub value: String, } @@ -19,12 +20,18 @@ impl Message { /// For subdiagnostics, we cannot check this. pub(crate) fn diag_message(&self, variant: Option<&VariantInfo<'_>>) -> TokenStream { let message = &self.value; - verify_fluent_message(self.message_span, &message, variant); + self.verify(variant); quote! { rustc_errors::DiagMessage::Inline(std::borrow::Cow::Borrowed(#message)) } } + + fn verify(&self, variant: Option<&VariantInfo<'_>>) { + verify_variables_used(self.message_span, &self.value, variant); + verify_message_style(self.message_span, &self.value); + verify_message_formatting(self.attr_span, self.message_span, &self.value); + } } -fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { +fn verify_variables_used(msg_span: Span, message_str: &str, variant: Option<&VariantInfo<'_>>) { // Parse the fluent message const GENERATED_MSG_ID: &str = "generated_msg"; let resource = @@ -53,8 +60,6 @@ fn verify_fluent_message(msg_span: Span, message_str: &str, variant: Option<&Var } } } - - verify_message_style(msg_span, message_str); } fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { @@ -120,3 +125,29 @@ fn verify_message_style(msg_span: Span, message: &str) { return; } } + +/// Verifies that the message is properly indented into the code +fn verify_message_formatting(attr_span: Span, msg_span: Span, message: &str) { + // Find the indent at the start of the message (`column()` is one-indexed) + let start = attr_span.unwrap().column() - 1; + + for line in message.lines().skip(1) { + if line.is_empty() { + continue; + } + let indent = line.chars().take_while(|c| *c == ' ').count(); + if indent < start { + span_err( + msg_span.unwrap(), + format!("message is not properly indented. {indent} < {start}"), + ) + .emit(); + return; + } + if indent % 4 != 0 { + span_err(msg_span.unwrap(), "message is not indented with a multiple of 4 spaces") + .emit(); + return; + } + } +} diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index c308f6126325f..55a8445744cba 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -708,7 +708,7 @@ impl SubdiagnosticVariant { } if !input.is_empty() { input.parse::()?; } if is_first { - message = Some(Message { message_span: inline_message.span(), value: inline_message.value() }); + message = Some(Message { attr_span: attr.span(), message_span: inline_message.span(), value: inline_message.value() }); is_first = false; } else { span_err(inline_message.span().unwrap(), "a diagnostic message must be the first argument to the attribute").emit(); From 99c6009c45fd2c1b7f4740b96d9c634d83ad4a5a Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Feb 2026 10:25:00 +0100 Subject: [PATCH 3/4] Reformat existing messages --- compiler/rustc_const_eval/src/errors.rs | 46 +++--- compiler/rustc_mir_build/src/errors.rs | 34 ++--- compiler/rustc_monomorphize/src/errors.rs | 6 +- compiler/rustc_parse/src/errors.rs | 2 +- compiler/rustc_passes/src/errors.rs | 4 +- compiler/rustc_trait_selection/src/errors.rs | 150 ++++++++++--------- 6 files changed, 122 insertions(+), 120 deletions(-) diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 3b49dbd907c8f..a673e0cb1efbd 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -106,9 +106,9 @@ pub(crate) struct UnstableInStableExposed { pub is_function_call2: bool, #[suggestion( "if the {$is_function_call2 -> - [true] caller - *[false] function -} is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", + [true] caller + *[false] function + } is not (yet) meant to be exposed to stable const contexts, add `#[rustc_const_unstable]`", code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n", applicability = "has-placeholders" )] @@ -300,11 +300,11 @@ pub(crate) struct UnallowedHeapAllocations { #[primary_span] #[label( r#"allocation not allowed in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] pub span: Span, pub kind: ConstContext, @@ -539,20 +539,20 @@ pub enum NonConstClosureNote { }, #[note( r#"function pointers need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] FnPtr, #[note( r#"closures need an RFC before allowed to be called in {$kind -> - [const] constant - [static] static - [const_fn] constant function - *[other] {""} -}s"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] Closure, } @@ -608,11 +608,11 @@ pub 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"# + [const] constant + [static] static + [const_fn] constant function + *[other] {""} + }s"# )] pub span: Span, pub kind: ConstContext, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 2474b3c49a612..fed0435f59a0d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -198,12 +198,12 @@ pub(crate) struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note("the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features + [1] feature + *[count] features } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it -*[count] them -} in `#[target_feature]`")] + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -532,12 +532,12 @@ pub(crate) struct CallToFunctionWithRequiresUnsafe { pub(crate) missing_target_features: DiagArgValue, pub(crate) missing_target_features_count: usize, #[note("the {$build_target_features} target {$build_target_features_count -> - [1] feature - *[count] features -} being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> - [1] it - *[count] them -} in `#[target_feature]`")] + [1] feature + *[count] features + } being enabled in the build configuration does not remove the requirement to list {$build_target_features_count -> + [1] it + *[count] them + } in `#[target_feature]`")] pub(crate) note: bool, pub(crate) build_target_features: DiagArgValue, pub(crate) build_target_features_count: usize, @@ -1264,9 +1264,9 @@ pub(crate) struct InterpretedAsConstSugg { pub(crate) enum SuggestLet { #[multipart_suggestion( "you might want to use `if let` to ignore the {$count -> -[one] variant that isn't -*[other] variants that aren't -} matched", + [one] variant that isn't + *[other] variants that aren't + } matched", applicability = "has-placeholders" )] If { @@ -1278,9 +1278,9 @@ pub(crate) enum SuggestLet { }, #[suggestion( "you might want to use `let...else` to handle the {$count -> -[one] variant that isn't -*[other] variants that aren't -} matched", + [one] variant that isn't + *[other] variants that aren't + } matched", code = " else {{ todo!() }}", applicability = "has-placeholders" )] diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index d045ae0b92cba..62a8743873bdb 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -162,9 +162,9 @@ pub(crate) struct AbiRequiredTargetFeature<'a> { #[primary_span] #[label( "function {$is_call -> -[true] called -*[false] defined -} here" + [true] called + *[false] defined + } here" )] pub span: Span, pub required_feature: &'a str, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index b54782ec592cb..fb77af1c19485 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1151,7 +1151,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { #[multipart_suggestion( "surround the {$num_statements -> [one] statement - *[other] statements + *[other] statements } with a body", applicability = "machine-applicable" )] diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 90b4d1b32bf7b..f420bba9b4e9c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1417,8 +1417,8 @@ pub(crate) struct DuplicateEiiImpls { pub second_crate: Symbol, #[note("in addition to these two, { $num_additional_crates -> - [one] another implementation was found in crate {$additional_crate_names} - *[other] more implementations were also found in the following crates: {$additional_crate_names} + [one] another implementation was found in crate {$additional_crate_names} + *[other] more implementations were also found in the following crates: {$additional_crate_names} }")] pub additional_crates: Option<()>, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index c904eb83896dc..013e4b522fb54 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -327,18 +327,18 @@ pub struct InferenceBadError<'a> { pub enum SourceKindSubdiag<'a> { #[suggestion( "{$kind -> -[with_pattern] consider giving `{$name}` an explicit type -[closure] consider giving this closure parameter an explicit type -*[other] consider giving this pattern a type -}{$x_kind -> -[has_name] , where the {$prefix_kind -> -*[type] type for {$prefix} -[const_with_param] value of const parameter -[const] value of the constant -} `{$arg_name}` is specified -[underscore] , where the placeholders `_` are specified -*[empty] {\"\"} -}", + [with_pattern] consider giving `{$name}` an explicit type + [closure] consider giving this closure parameter an explicit type + *[other] consider giving this pattern a type + }{$x_kind -> + [has_name] , where the {$prefix_kind -> + *[type] type for {$prefix} + [const_with_param] value of const parameter + [const] value of the constant + } `{$arg_name}` is specified + [underscore] , where the placeholders `_` are specified + *[empty] {\"\"} + }", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -356,15 +356,15 @@ pub enum SourceKindSubdiag<'a> { }, #[label( "cannot infer {$is_type -> -[true] type -*[false] the value -} of the {$is_type -> -[true] type -*[false] const -} {$parent_exists -> -[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` -*[false] parameter {$param_name} -}" + [true] type + *[false] the value + } of the {$is_type -> + [true] type + *[false] const + } {$parent_exists -> + [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` + *[false] parameter {$param_name} + }" )] GenericLabel { #[primary_span] @@ -377,9 +377,9 @@ pub enum SourceKindSubdiag<'a> { }, #[suggestion( "consider specifying the generic {$arg_count -> -[one] argument -*[other] arguments -}", + [one] argument + *[other] arguments + }", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -945,9 +945,9 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -956,9 +956,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_2: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -966,9 +966,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -977,9 +977,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + [true] ... + *[false] {\"\"} + }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" )] ExpectedSignatureNothing { leading_ellipsis: bool, @@ -987,9 +987,9 @@ pub enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -998,9 +998,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_2: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1008,9 +1008,9 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1019,9 +1019,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + [true] ... + *[false] {\"\"} + }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" )] ExpectedPassiveNothing { leading_ellipsis: bool, @@ -1029,9 +1029,9 @@ pub enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, #[note("{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -1041,9 +1041,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." )] ExpectedOtherAny { leading_ellipsis: bool, @@ -1053,9 +1053,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." )] ExpectedOtherSome { leading_ellipsis: bool, @@ -1065,9 +1065,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "{$leading_ellipsis -> -[true] ... -*[false] {\"\"} -}`{$ty_or_sig}` must implement `{$trait_path}`" + [true] ... + *[false] {\"\"} + }`{$ty_or_sig}` must implement `{$trait_path}`" )] ExpectedOtherNothing { leading_ellipsis: bool, @@ -1076,9 +1076,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but it actually implements `{$trait_path}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1087,9 +1087,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1099,9 +1099,9 @@ pub enum ActualImplExplNotes<'tcx> { }, #[note( "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> -[true] , for some specific lifetime `'{$lifetime}` -*[false] {\"\"} -}" + [true] , for some specific lifetime `'{$lifetime}` + *[false] {\"\"} + }" )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, @@ -1246,7 +1246,7 @@ pub struct TraitImplDiff { pub trait_sp: Span, #[note( "expected signature `{$expected}` - {\" \"}found signature `{$found}`" + {\" \"}found signature `{$found}`" )] pub note: (), #[subdiagnostic] @@ -1940,10 +1940,12 @@ pub enum ObligationCauseFailureCode { #[primary_span] span: Span, }, - #[diag("{$lang_item_name -> -[panic_impl] `#[panic_handler]` -*[lang_item_name] lang item `{$lang_item_name}` -} function has wrong type", code = E0308)] + #[diag( + "{$lang_item_name -> + [panic_impl] `#[panic_handler]` + *[lang_item_name] lang item `{$lang_item_name}` + } function has wrong type" + , code = E0308)] FnLangCorrectType { #[primary_span] span: Span, From 6babe687a50440ae6a1d60a748f6a1f809b56d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 5 Feb 2026 15:57:14 +0100 Subject: [PATCH 4/4] Port rustc_reservation_impl to the new attribute parser --- .../src/attributes/rustc_internal.rs | 26 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../rustc_hir/src/attrs/data_structures.rs | 3 +++ .../rustc_hir/src/attrs/encode_cross_crate.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 3 ++- compiler/rustc_passes/src/check_attr.rs | 2 +- .../src/traits/coherence.rs | 9 +++---- .../src/traits/select/mod.rs | 9 +++---- 8 files changed, 42 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index cbf4af8ce4f4d..0fd8c8a04a57a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -873,3 +873,29 @@ impl NoArgsAttributeParser for RustcStrictCoherenceParser { ]); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence; } + +pub(crate) struct RustcReservationImplParser; + +impl SingleAttributeParser for RustcReservationImplParser { + const PATH: &[Symbol] = &[sym::rustc_reservation_impl]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]); + + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let Some(nv) = args.name_value() else { + cx.expected_name_value(args.span().unwrap_or(cx.attr_span), None); + return None; + }; + + let Some(value_str) = nv.value_as_str() else { + cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit())); + return None; + }; + + Some(AttributeKind::RustcReservationImpl(cx.attr_span, value_str)) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index afbb70654f4d0..ddb5ae33bc98e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -209,6 +209,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index ef790fe76b74f..d9c4179cca839 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1219,6 +1219,9 @@ pub enum AttributeKind { /// Represents `#[rustc_regions]` RustcRegions, + /// Represents `#[rustc_reservation_impl]` + RustcReservationImpl(Span, Symbol), + /// Represents `#[rustc_scalable_vector(N)]` RustcScalableVector { /// The base multiple of lanes that are in a scalable vector, if provided. `element_count` diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index cba7679d2df31..d55cb1d6f66a4 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -151,6 +151,7 @@ impl AttributeKind { RustcPubTransparent(..) => Yes, RustcReallocator => No, RustcRegions => No, + RustcReservationImpl(..) => Yes, RustcScalableVector { .. } => Yes, RustcShouldNotBeCalledOnConstItems(..) => Yes, RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f3086266eec00..219e44cd2e275 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1275,7 +1275,8 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader .of_trait .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); let selfty = tcx.type_of(def_id).instantiate_identity(); - let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let is_rustc_reservation = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(..)); check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd0de90d575b5..3f89ff577d596 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -342,6 +342,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcPreserveUbChecks | AttributeKind::RustcReallocator | AttributeKind::RustcRegions + | AttributeKind::RustcReservationImpl(..) | AttributeKind::RustcScalableVector { .. } | AttributeKind::RustcShouldNotBeCalledOnConstItems(..) | AttributeKind::RustcSimdMonomorphizeLaneLimit(..) @@ -396,7 +397,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_trivial_field_reads | sym::rustc_on_unimplemented | sym::rustc_do_not_const_check - | sym::rustc_reservation_impl | sym::rustc_doc_primitive | sym::rustc_conversion_suggestion | sym::rustc_deprecated_safe_2024 diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9f59f6c592509..fc628e78a3e23 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -8,8 +8,10 @@ use std::fmt::Debug; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; +use rustc_hir::find_attr; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::PredicateObligations; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -23,7 +25,7 @@ use rustc_middle::ty::{ }; pub use rustc_next_trait_solver::coherence::*; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; -use rustc_span::{DUMMY_SP, Span, sym}; +use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument, warn}; use super::ObligationCtxt; @@ -758,10 +760,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { } = cand.kind() && let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) { - let message = infcx - .tcx - .get_attr(def_id, sym::rustc_reservation_impl) - .and_then(|a| a.value_str()); + let message = find_attr!(infcx.tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { self.causes.insert(IntercrateAmbiguityCause::ReservationImpl { message }); } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 787dd4ea62549..4469afc3a4ebf 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -12,9 +12,9 @@ use rustc_data_structures::assert_matches; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diag, EmissionGuarantee}; -use rustc_hir as hir; -use rustc_hir::LangItem; +use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, LangItem, find_attr}; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::at::ToTrace; @@ -33,7 +33,7 @@ use rustc_middle::ty::{ may_use_unstable_feature, }; use rustc_next_trait_solver::solve::AliasBoundKind; -use rustc_span::{Symbol, sym}; +use rustc_span::Symbol; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -1445,8 +1445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { && let ty::ImplPolarity::Reservation = tcx.impl_polarity(def_id) { if let Some(intercrate_ambiguity_clauses) = &mut self.intercrate_ambiguity_causes { - let message = - tcx.get_attr(def_id, sym::rustc_reservation_impl).and_then(|a| a.value_str()); + let message = find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcReservationImpl(_, message) => *message); if let Some(message) = message { debug!( "filter_reservation_impls: \