diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index fafac7ea909da..e02d71a261581 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -47,6 +47,7 @@ pub(crate) mod link_attrs; pub(crate) mod lint_helpers; pub(crate) mod loop_match; pub(crate) mod macro_attrs; +pub(crate) mod must_not_suspend; pub(crate) mod must_use; pub(crate) mod no_implicit_prelude; pub(crate) mod no_link; diff --git a/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs new file mode 100644 index 0000000000000..8456ce7977587 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs @@ -0,0 +1,35 @@ +use super::prelude::*; + +pub(crate) struct MustNotSuspendParser; + +impl SingleAttributeParser for MustNotSuspendParser { + const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Struct), + Allow(Target::Enum), + Allow(Target::Union), + Allow(Target::Trait), + ]); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let reason = match args { + ArgParser::NameValue(reason) => match reason.value_as_str() { + Some(val) => Some(val), + None => { + cx.expected_nv_or_no_args(reason.value_span); + return None; + } + }, + ArgParser::NoArgs => None, + ArgParser::List(list) => { + cx.expected_nv_or_no_args(list.span); + return None; + } + }; + + Some(AttributeKind::MustNotSupend { reason }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 835bf8ae5c9c4..0217b6370408d 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -51,6 +51,7 @@ use crate::attributes::macro_attrs::{ AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser, MacroUseParser, }; +use crate::attributes::must_not_suspend::MustNotSuspendParser; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::no_link::NoLinkParser; @@ -89,7 +90,6 @@ use crate::session_diagnostics::{ AttributeParseError, AttributeParseErrorReason, ParsedDescription, }; use crate::target_checking::AllowedTargets; - type GroupType = LazyLock>; pub(super) struct GroupTypeInner { @@ -208,6 +208,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 a5ecfa45fb408..b3c1974c00313 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -824,6 +824,9 @@ pub enum AttributeKind { /// Represents `#[move_size_limit]` MoveSizeLimit { attr_span: Span, limit_span: Span, limit: Limit }, + /// Represents `#[must_not_suspend]` + MustNotSupend { reason: Option }, + /// Represents `#[must_use]`. MustUse { span: Span, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index efdb4f2f22b2e..e02e954c94a5f 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -71,6 +71,7 @@ impl AttributeKind { Marker(..) => No, MayDangle(..) => No, MoveSizeLimit { .. } => No, + MustNotSupend { .. } => Yes, MustUse { .. } => Yes, Naked(..) => No, NoCore(..) => No, diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 7fad380ba5a19..705551c58f320 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -64,9 +64,9 @@ use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; -use rustc_hir as hir; +use rustc_hir::attrs::AttributeKind; use rustc_hir::lang_items::LangItem; -use rustc_hir::{CoroutineDesugaring, CoroutineKind}; +use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind, find_attr}; use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec, indexvec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -85,7 +85,6 @@ use rustc_mir_dataflow::{ }; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::source_map::dummy_spanned; -use rustc_span::symbol::sym; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::TyCtxtInferExt as _; @@ -1989,11 +1988,11 @@ fn check_must_not_suspend_def( hir_id: hir::HirId, data: SuspendCheckData<'_>, ) -> bool { - if let Some(attr) = tcx.get_attr(def_id, sym::must_not_suspend) { - let reason = attr.value_str().map(|s| errors::MustNotSuspendReason { - span: data.source_span, - reason: s.as_str().to_string(), - }); + if let Some(reason_str) = + find_attr!(tcx.get_all_attrs(def_id), AttributeKind::MustNotSupend {reason} => reason) + { + let reason = + reason_str.map(|s| errors::MustNotSuspendReason { span: data.source_span, reason: s }); tcx.emit_node_span_lint( rustc_session::lint::builtin::MUST_NOT_SUSPEND, hir_id, diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 21a6c4d653bc5..d4c58f7fe05d9 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -323,7 +323,7 @@ impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> { pub(crate) struct MustNotSuspendReason { #[primary_span] pub span: Span, - pub reason: String, + pub reason: Symbol, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 39ad541ee85a9..9628e6d4efe93 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -376,10 +376,6 @@ passes_must_implement_not_function_note = all `#[rustc_must_implement_one_of]` a passes_must_implement_not_function_span_note = required by this annotation -passes_must_not_suspend = - `must_not_suspend` attribute should be applied to a struct, enum, union, or trait - .label = is not a struct, enum, union, or trait - passes_no_main_function = `main` function not found in crate `{$crate_name}` .here_is_main = here is a function named `main` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 717a0e54d0c6e..c9357b99cea20 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -308,6 +308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::ThreadLocal | AttributeKind::CfiEncoding { .. } | AttributeKind::RustcHasIncoherentInherentImpls + | AttributeKind::MustNotSupend { .. } ) => { /* do nothing */ } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); @@ -325,7 +326,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::rustc_dirty, ..] | [sym::rustc_if_this_changed, ..] | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr), - [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => { self.check_autodiff(hir_id, attr, span, target) } @@ -1197,16 +1197,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait. - fn check_must_not_suspend(&self, attr: &Attribute, span: Span, target: Target) { - match target { - Target::Struct | Target::Enum | Target::Union | Target::Trait => {} - _ => { - self.dcx().emit_err(errors::MustNotSuspend { attr_span: attr.span(), span }); - } - } - } - /// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl. fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) { if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index ace738c559a42..49b9618ef2af9 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -194,15 +194,6 @@ pub(crate) struct BothFfiConstAndPure { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_must_not_suspend)] -pub(crate) struct MustNotSuspend { - #[primary_span] - pub attr_span: Span, - #[label] - pub span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_link)] #[warning] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index fd6f34fb45e29..fc644668735ed 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -32,21 +32,6 @@ error: malformed `patchable_function_entry` attribute input LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` -error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:138:1 - | -LL | #[must_not_suspend()] - | ^^^^^^^^^^^^^^^^^^^^^ - | -help: the following are the possible correct uses - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend = "reason"] - | -LL - #[must_not_suspend()] -LL + #[must_not_suspend] - | - error: malformed `allow` attribute input --> $DIR/malformed-attrs.rs:184:1 | @@ -527,6 +512,22 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error[E0539]: malformed `must_not_suspend` attribute input + --> $DIR/malformed-attrs.rs:138:1 + | +LL | #[must_not_suspend()] + | ^^^^^^^^^^^^^^^^^^--^ + | | + | didn't expect a list here + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[must_not_suspend(count)] + | +++++ +LL - #[must_not_suspend()] +LL + #[must_not_suspend] + | + error[E0539]: malformed `cfi_encoding` attribute input --> $DIR/malformed-attrs.rs:140:1 | diff --git a/tests/ui/lint/must_not_suspend/other_items.rs b/tests/ui/lint/must_not_suspend/other_items.rs index 7a42a2bba03b0..1c46cce7ed3ab 100644 --- a/tests/ui/lint/must_not_suspend/other_items.rs +++ b/tests/ui/lint/must_not_suspend/other_items.rs @@ -2,7 +2,7 @@ #![feature(must_not_suspend)] #![deny(must_not_suspend)] -#[must_not_suspend] //~ ERROR attribute should be +#[must_not_suspend] //~ ERROR attribute cannot be used on modules mod inner {} fn main() {} diff --git a/tests/ui/lint/must_not_suspend/other_items.stderr b/tests/ui/lint/must_not_suspend/other_items.stderr index dff5210b7e47f..999a9d2fb3dc8 100644 --- a/tests/ui/lint/must_not_suspend/other_items.stderr +++ b/tests/ui/lint/must_not_suspend/other_items.stderr @@ -1,10 +1,10 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait +error: `#[must_not_suspend]` attribute cannot be used on modules --> $DIR/other_items.rs:5:1 | LL | #[must_not_suspend] | ^^^^^^^^^^^^^^^^^^^ -LL | mod inner {} - | ------------ is not a struct, enum, union, or trait + | + = help: `#[must_not_suspend]` can be applied to data types, traits, and unions error: aborting due to 1 previous error diff --git a/tests/ui/lint/must_not_suspend/return.rs b/tests/ui/lint/must_not_suspend/return.rs index a04f6a4cfb430..de78ee0f92998 100644 --- a/tests/ui/lint/must_not_suspend/return.rs +++ b/tests/ui/lint/must_not_suspend/return.rs @@ -2,7 +2,7 @@ #![feature(must_not_suspend)] #![deny(must_not_suspend)] -#[must_not_suspend] //~ ERROR attribute should be +#[must_not_suspend] //~ ERROR attribute cannot be used on functions fn foo() -> i32 { 0 } diff --git a/tests/ui/lint/must_not_suspend/return.stderr b/tests/ui/lint/must_not_suspend/return.stderr index 440f816568622..1a81b1a39f0c8 100644 --- a/tests/ui/lint/must_not_suspend/return.stderr +++ b/tests/ui/lint/must_not_suspend/return.stderr @@ -1,12 +1,10 @@ -error: `must_not_suspend` attribute should be applied to a struct, enum, union, or trait +error: `#[must_not_suspend]` attribute cannot be used on functions --> $DIR/return.rs:5:1 | -LL | #[must_not_suspend] - | ^^^^^^^^^^^^^^^^^^^ -LL | / fn foo() -> i32 { -LL | | 0 -LL | | } - | |_- is not a struct, enum, union, or trait +LL | #[must_not_suspend] + | ^^^^^^^^^^^^^^^^^^^ + | + = help: `#[must_not_suspend]` can be applied to data types, traits, and unions error: aborting due to 1 previous error